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

来源:互联网 发布:c# utf8 java转换 编辑:程序博客网 时间:2024/05/22 07:54

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
43149512345732145679261025520
 

Sample Output
Case #1: 999Case #2: 53123Case #3: 7166666Case #4: 615015015
 

Source
2017ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)
 

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;}


阅读全文
0 0