2017 ACM/ICPC 沈阳 G题 Infinite Fraction Path

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 that this talent can help him find the best infinite fraction path before the anniversary. 
The kingdom has N cities numbered from 0 to N - 1 and you are given an array D[0 ... N - 1] of decimal digits (0 ≤ D[i] ≤ 9, D[i] is an integer). The destination of the only one-way road start from the i-th city is the city labelled ( i2i2 + 1)%N. 
A path beginning from the i-th city would pass through the cities u1,u2,u3u1,u2,u3, and so on consecutively. The path constructs a real number A[i], called the relevant fraction such that the integer part of it is equal to zero and its fractional part is an infinite decimal fraction with digits D[i], D[u1u1], D[u2u2], and so on. 
The best infinite fraction path is the one with the largest relevant fraction

InputThe input contains multiple test cases and the first line provides an integer up to 100 indicating to the total numberof test cases. 
For each test case, the first line contains the integer N (1 ≤ N ≤ 150000). The second line contains an array ofdigits D, given without spaces. 
The summation of N is smaller than 2000000. 
OutputFor each test case, you should output the label of the case first. Then you are to output exactly N characters which are the first N digits of the fractional part of the largest relevant fraction. 
Sample Input

4
3
149
5
12345
7
3214567
9
261025520

Sample Output

Case #1: 999
Case #2: 53123
Case #3: 7166666
Case #4: 615015015
题解:

若想数字较大,那么这个数字的最高位越大越好,再是次高位,再次次高…那么我们可以先找出这些点中权值最大的点作为起始点放入队列中,然后一步步做广度优先搜索,依次排除组成数字较小的起始点。最后剩下的那个点就是答案。
  但是这个肯定超时,复杂度最大为O(n2)O(n2),仔细想想会发现这个图有很多特点:图由许多单向链和环构成;有的链连接到了其他链的中间;所有链的末尾肯定连接一个环。而超时的原因肯定是许多点都被重复搜索多次了。这里可能有一个点被多个起始点搜索过(链的分支出);一个点被一个起始点一直搜索(环)。
  于是朝这个方向优化:
  1.同一层(step)里,我们只要那些当前权值最大的点对应的起始点。
  2.对于链的分支而言:假如初始点AA搜索到一个已经被点BB搜索过的点,那么初始点BB就不用继续搜索了(想想为什么),BB就可以被移出队列。

参考代码:
#include<bits/stdc++.h>
#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=250010;
int Max,vis[maxn],tot;
char a[maxn],ans[maxn];
ll n;
struct Node{
    int step;
    ll pos;
    Node() {}
    Node(int step,ll pos):step(step),pos(pos) {}
};
queue<Node >q;
inline void bfs()
{
    Node s;
    while(!q.empty())
    {
        s=q.front();q.pop();
        if(s.step==n) continue;
        if(a[s.pos]==ans[s.step])
        {
            if(vis[s.pos]==s.step) continue;
            vis[s.pos]=s.step;
            s.pos= (s.pos * s.pos + 1) % n;
            s.step++;
            if(a[s.pos]>=ans[s.step])
            {
                ans[s.step]=a[s.pos];
                q.push(s);
            }
        }
    }
}
int main()
{
    int T;
    cin>>T;
    for(int cas=1;cas<=T;++cas)
    {
        while(!q.empty()) q.pop();
        tot=0;
        scanf("%lld",&n);
        Max=0;
        scanf("%s",a);
        for(int i=0; i<n; i++) Max=max(Max,(int)a[i]);
        for(int i=0; i<n; i++) if(a[i]==Max) q.push(Node(1,i));
        CLR(ans,-1); CLR(vis,-1);
        ans[1]=Max;
        bfs();
        printf("Case #%d: ",cas);
        ans[n+1]='\0';
        printf("%s\n",ans+1);
    }
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/songorz/p/9784964.html