HDU6223——2017ICPC徐州G Infinite Fraction Path

题意:

  给定一个数字串,每个位子都能向(i*i+1)%n的位子转移,输出路径上,字典序最大的,长度为n的串。

参考:https://www.cnblogs.com/mountaink/p/9541442.html

思路:

  BFS,

  一个数字肯定是最高位越大,这个数字本身就越大,所以肯定第一位要取最大值,在这一位取最大值的时候后面每一位都要尽量最大,所以想到bfs。

但是bfs肯定要剪枝,怎么剪枝呢?

  1、按照思路,我要取每一位尽可能大的值,所以某一个状态的某一位小于我当前以及有的解,这个状态肯定被舍弃。

    这是最好想的思路,但是如果对于一个全是9的数列,这个剪枝完全没有用,所以必须有其他的剪枝。

  2、如果到了从不同起点到达某一个位置,在答案数列中的层次是一样的,舍弃掉。(换句话说,不同起点经过相同步数到达同一座城市,那么后续的状态都是一样的了,所以没必要再走下去),

具体怎么实现呢,一开始将数列中所有最大值所在的位置入队,对于某一种状态,看他的下一步是否比答案中更优或者相等(答案数组初始化为-1),如果更优或者相等则重新入队。 对于新状态,先检查一下当前位置的值是不是和答案数组中当前位置的最大值相等,如果不相等,舍弃,如果相等,判断一下有没有状态在相同步数的情况下已经走到这一步了,有则舍弃,没有则更新一下,然后重复上述操作。

// #pragma GCC optimize(3)
// #pragma comment(linker, "/STACK:102400000,102400000")  //c++
// #pragma GCC diagnostic error "-std=c++11"
// #pragma comment(linker, "/stack:200000000")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue

typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl ‘\n‘

#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x7f7f7f7f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e8+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<‘0‘||ch>‘9‘) f|=(ch==‘-‘),ch=getchar();
    while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x=f?-x:x;
}

/*-----------------------showtime----------------------*/
            const int maxn = 150009;
            int d[maxn],n;
            char str[maxn];
            struct node
            {
                ll u,cur,pos;
                node(){}
                node(int u,int pos ,int cur):u(u),pos(pos),cur(cur){}
            };
            queue<node> q;//这是一个大根堆q
            int dep[maxn],vis[maxn];
int main(){
            int T;  scanf("%d", &T);
            for(int tt=1; tt<=T; tt++){
                scanf("%d%s", &n, str);

                // memset(dep, -1, sizeof(dep));
                // memset(vis, -1, sizeof(vis));
                int mx = 0;
                for(int i=0; i<n; i++)
                    d[i] = (int)(str[i] - ‘0‘), mx = max(mx, d[i]);
                memset(vis,-1,sizeof(vis));
                memset(dep,-1,sizeof(dep));
                for(int i=0; i<n; i++)
                    if(d[i] == mx) q.push(node(d[i], i, 0));
                while(!q.empty()){
                    node tmp = q.front(); q.pop();
                    if(tmp.cur == n)break;          //第n个确定
                    if(dep[tmp.cur] > tmp.u)continue;
                    else if(dep[tmp.cur] == tmp.u && vis[tmp.pos] == tmp.cur)continue;  //同一个pos,第二次来
                    else {
                        dep[tmp.cur] = tmp.u;
                        vis[tmp.pos] = tmp.cur;
                        ll nx = (1ll*tmp.pos * tmp.pos + 1ll)%(1ll*n);
                        // if(tmp.cur==n-1)break;
                        dep[tmp.cur+1] = max(dep[tmp.cur+1] ,d[nx]);
                        q.push(node(d[nx], nx, tmp.cur+1));
                    }
                }
                while(!q.empty())q.pop();
                printf("Case #%d: ", tt);
                for(int i=0; i<n; i++) printf("%d", dep[i]);
                printf("\n");
            }

            return 0;
}

HDU 6223

原文地址:https://www.cnblogs.com/ckxkexing/p/9934540.html

时间: 2024-08-30 03:57:42

HDU6223——2017ICPC徐州G Infinite Fraction Path的相关文章

HDU6223 &amp;&amp; 2017沈阳ICPC: G. Infinite Fraction Path——特殊图&amp;&amp;暴力

题意 给定一个数字串,每个位子都能向(i*i+1)%n的位子转移,输出在路径上.字典序最大的.长度为n的串($n \leq 150000$). 分析 先考虑一个暴力的方法,考虑暴力每个x,然后O(n)判定形成的字符串字典序是否比当前的最优解要大,复杂度O(n²),显然大家都会做. 而本题中有个结论:没有必要每次O(n),只要前100个字符一样,那么后面的一定都一样!所以>500直接break,复杂度O(500n), 可以过! 理解:对于所有的下标k,k向(k*k+1)%n连一条有向边,最后可以得

ACM-ICPC 2017 沈阳赛区现场赛 G. Infinite Fraction Path &amp;&amp; HDU 6223

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6223 参考题解:https://blog.csdn.net/qq_40482495/article/details/78492841 注意优先队列自定义比较级的用法!! 1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned long long 5 #define

hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)

题目传送门 题目大意:给出n座城市,每个城市都有一个0到9的val,城市的编号是从0到n-1,从i位置出发,只能走到(i*i+1)%n这个位置,从任意起点开始,每走一步都会得到一个数字,走n-1步,会得到一个长度为n的数列,输出能得到的最大的数列(当成数字). 思路: 一个数字肯定是最高位越大,这个数字本身就越大,所以肯定第一位要取最大值,在这一位取最大值的时候后面每一位都要尽量最大,所以想到bfs. 但是bfs肯定要剪枝,怎么剪枝呢? 1.按照思路,我要取每一位尽可能大的值,所以某一个状态的某

HDU 6223 Infinite Fraction Path(BFS+剪枝)

The ant Welly now dedicates himself to urban infrastructure. He came to the kingdom of numbers and solicited an audience with the king. He recounted how he had built a happy path in the kingdom of happiness. The king affirmed Welly's talent and hoped

【HDOJ6223】Infinite Fraction Path(后缀数组)

题意: 给一个长度为n的字符串s[0..n-1],但i的后继不再是i+1,而是(i*i+1)%n,求所有长度为n的"子串"中,字典序最大的是谁 n<=150000,s[i]=0..9 思路:后缀数组 因为前驱与后继的关系已经变化,就不能用下标直接加减 i的后继是唯一的,i的前驱却不一定 所以对于后继使用倍增,对于前驱每个位置暴力开队列存储,需要的时候再拿出来 在判断的地方稍作修改 1 #include<cstdio> 2 #include<cstring>

hdu 6223 Infinite Fraction Path

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6223 题意:给定长度为n的一串数字S,现在要按照一种规则寻找长度为n的数字串,使得该数字串的字典序最大.规则:从数字串S的某一个下标为x的数字出发,可以到达的下一个数字是下标为(x*x+1)%n的数字. 思路:BFS+剪枝.剪枝技巧: 1:遍历到某一层的节点时,记录已经到达过的节点,下次如果还经过就直接不考虑. 2:当前遍历到的某一层节点的数字较之前的小,直接不考虑. AC代码: #define _

SGU 232 Infinite Fraction Hash

题目链接:点击打开链接 #include <cstdio> #include <cstring> typedef unsigned long long ll; const int key = (int)(1e9) + 7; const int N = 150010; char b[N], a[N + N]; ll xp[N], h[N + N]; int len; void get() { char ch; while ((ch = getchar()) < '0' || c

真题演练1

ACM-ICPC 2017 Asia Shenyan F. Heron and His Triangle 三边长给出,海伦公式算出面积,暴力枚举整数情况,得: 4,14,52,194,724等数据 之后就要灵性找规律了,得:a[i] = a[i-1]*4-a[i-2] 总结:1.对于类似题目,暴力枚举出一大串数据之后,应该第一时间反应过来找规律. 2.大数题应考虑java或python写(java暂时不会) a={} a[1]=4 a[2]=14 for i in range(3,61,1):

2017 ICPC/ACM 沈阳区域赛HDU6223

Infinite Fraction Path Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1262    Accepted Submission(s): 224 Problem Description The ant Welly now dedicates himself to urban infrastructure. He c