2017ICPC沈阳现场赛G(倍增思想)

Infinite Fraction Path

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 279    Accepted Submission(s): 34


Problem Description
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 ( i2 + 1)%N.
A path beginning from the i-th city would pass through the cities  u1,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[ u1], D[ u2], and so on.
The best infinite fraction path is the one with the largest relevant fraction
 

Input
The 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.
 

Output
For 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
 

Source
 

Recommend

jiangzijing2015


解题思路:令ans[i][j]为以i为起点,长度为2^j的路径就行,类似于后缀数组中的基数排序一样,我这里做了一点变化,每次得到新的rank时,用上一次的两个关键字来计算,用第一关键字乘上一个比最大的第二关键字大的数就行,然后把这个乘积加上第二关键字就行,然后排序,得到新的rank,复杂度(O(n * logn * logn)),其实应该还有更好的解法,就是用后缀数组里面的基数排序中的思想就行。


#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 150000 + 10;
int N;
char D[maxn];
int Nxt[maxn];
int dp[maxn];
int Rank[maxn];
char res[maxn];
int temp[maxn];
struct node
{
    int id;
    LL value;
    bool operator <(const node &res) const
    {
        return value < res.value;
    }
} Node[maxn];
int main()
{
    int T;
    //freopen("C:\\Users\\creator\\Desktop\\in1.txt","r",stdin) ;
    //freopen("C:\\Users\\creator\\Desktop\\out.txt","w",stdout) ;
    scanf("%d", &T);

    int Case = 1;
    while(T--)
    {
        scanf("%d", &N);
        scanf("%s", D);
        for(int i = 0; i < N; i++)
        {
            LL x = (LL)i * (LL)i + 1;
            x %= (LL)N;
            Nxt[i] = x;
            dp[i] = i;
        }
        if(N == 1)
        {
            printf("Case #%d: %s\n", Case++, D);
            continue;
        }
        for(int i = 0; i < N; i++)
        {
            Rank[i] = (D[i] - '0');
        }
        int w = 1;
        int ans = -1;
        while(true)
        {
            for(int i = 0; i < N; i++)
            {
                Node[i].id = i;
                LL Nxt1 = dp[i];
                Nxt1 = Nxt[Nxt1];
                temp[i] = dp[Nxt1];
                Node[i].value = (LL)Rank[i] * (LL)(maxn + 1) + (LL)Rank[Nxt1];
            }
            sort(Node, Node + N);
            int p = -1;
            for(int i = 0; i < N; i++)
            {
                dp[i] = temp[i];
                int id = Node[i].id;
                if(i == 0) Rank[id] = ++p;
                else
                {
                    if(Node[i].value == Node[i - 1].value) Rank[id] = p;
                    else Rank[id] = ++p;
                }
            }
            if((1<<w) >= N)
            {
                LL Max = -1;
                for(int i = 0; i < N; i++)
                {
                    if(Rank[i] > Max)
                    {
                        Max = Rank[i];
                        ans = i;
                    }
                }
                break;
            }
            w++;
        }
        int depth = 0;
        res[depth++] = D[ans];
        while(depth < N)
        {
            ans = Nxt[ans];
            res[depth++] = D[ans];
        }
        res[N] = '\0';
        printf("Case #%d: %s\n", Case++, res);
    }

    return 0;
}


猜你喜欢

转载自blog.csdn.net/creatorx/article/details/78478663