sgu 232

来源:互联网 发布:新华保险金彩一生算法 编辑:程序博客网 时间:2024/05/27 21:02

(imodk)modn=(jmodk)modnij=pk+qn=tgcd(n,k)
所以问题转变为:有gcd(n,k)个本质不同的字符串,每个字符串长度都为 n/gcd(n,k) , 求它们中字典序最大的字符串。


最大表示法。 时间复杂度 O(n)


注意输出时要补成 n 位。


#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>const int maxn = 150005;int n, k, len;char d[maxn];bool hash[maxn];char s[maxn<<1];int sl;char ans[maxn];int at;int gcd(int a,int b){    return (!b)?a:gcd(b,a%b);}int getmax(){    for(int i = 0; i < sl; i++)        s[i+sl] = s[i];    int i = 0, j = 1, k = 0;    while(i < sl && j < sl)    {        if(k == sl) break;        if(s[i+k] > s[j+k])            j += k+1, k = 0;        else if(s[i+k] < s[j+k])            i += k+1, k = 0;        else            k++;                if(i == j) j++;    }    return i;}bool compare(int t, int x){    for(int i = 0; i < len; i++)    {        if(d[t] > d[x])            return true;        else if(d[t] < d[x])            return false;        else        {            t = (t+k)%n;            x = (x+k)%n;        }    }    return false;}int main(){#ifndef ONLINE_JUDGE    freopen("sgu232.in","r",stdin);    freopen("sgu232.out","w",stdout);#endif    std::cin >> n >> k;    scanf("%s", d);    len = n/gcd(n,k);    for(int i = 0; i < n; i++)        if(!hash[i])        {            int t = i; sl = 0;            while(!hash[t])            {                hash[t] = true;                s[sl++] = d[t];                t = (t+k)%n;            }            int st = ((long long)k*getmax() + i)%n;            if(compare(st, at)) at = st;        }     for(int i = 0; i < n; i++)        ans[i] = d[at], at = (at+k)%n;    printf("%s", ans);#ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);#endif    return 0;           }
0 0
原创粉丝点击