UVa:306 Cipher

来源:互联网 发布:java map 顺序 编辑:程序博客网 时间:2024/05/01 17:10

这个题去年就看到了,但是用模拟的办法超时了。如果每次模拟都记录下字符串还会内存超限。后来得知是置换群。每个字符的出现都是有周期的,这样整个串的周期就是所有字符周期的最小公倍数数。如果求了串的周期,k取模之后再模拟,还是会超时。正确的办法是k对每个字符的周期取模,然后对字符操作。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <vector>#include <map>#include <string>#include <algorithm>#define ll long long#define INF 2139062143#define MAXN 5000000//ios::sync_with_stdio(false);using namespace std;int num[205],n,r[205];void Init(){    for(int i=1; i<=n; ++i)    {            int now=num[i],ed=i,cir=1;            while(now!=ed)            {                cir++;                now=num[now];            }            r[i]=cir;    }}void Set_text(char *str){    int l=strlen(str+1);    for(int i=l+1; i<=n; ++i)        str[i]=' ';    str[n+1]=0;}void solve(char *str1,char *str2,int k){    for(int i=1; i<=n; ++i)    {        int ed=(k-1)%r[i]+1,now=i;        for(int j=0; j<ed; ++j)            now=num[now];        str2[now]=str1[i];    }    str2[n+1]=0;}int main(){    while(scanf("%d",&n)&&n)    {        for(int i=1; i<=n; ++i)            scanf("%d",&num[i]);        Init();        char str1[205],str2[205];        int k;        while(scanf("%d",&k)&&k)        {            char c;            getchar();            gets(str1+1);            Set_text(str1+1);            solve(str1,str2,k);            printf("%s\n",str2+1);        }        printf("\n");    }    return 0;}


 

0 0
原创粉丝点击