http://acm.pku.edu.cn/JudgeOnline/problem?id=1026
題意是:給出n個數字出現的順序,給出一個字串加密的次數k,再給一串字串,長度少於n,用空格補全;按著每個字元所處位置的數字進行排序加密,我們可以發現每個數字經過x次加密就能構成一個迴圈,這樣我們只要找到這個重複持續時間x,就好了,加密次數k要用到模運算來處理,這樣才不會逾時。
加密方式如題中所給:
1 2 3 4 5 6 7 8 9 10
4 5 3 7 2 8 1 6 10 9
對於第一個字元,加密3次的結果如下:
1 --> 4 --> 7 -->1
對於第二個字元,加密2次的結果如下:
2 --> 5 --> 2
可以看到,加密一定次數後,結果會構成一個迴圈,如果我們求出這個重複持續時間,那麼加密的次數就可以使用取餘運算進行縮減了。
#include<iostream><br />using namespace std;<br />#define MAX 201<br />int n, T[MAX], key[MAX];<br />void fun()//求置換重複持續時間<br />{<br />int i,j,count;<br />for(i=1; i<=n; i++)<br />{<br />j = key[i];<br />count = 1;<br />while(i != j)//直到回到自己本身,就是一個置換重複持續時間;<br />{<br />count++;<br />j = key[j];<br />}<br />T[i] = count;//第i數位重複持續時間數存放在T[i]中;<br />}<br />}<br />int main()<br />{<br />int i,j,k,len,pos;<br />char str[MAX], ch[MAX];<br />while(scanf("%d",&n) != EOF)<br />{<br />if(n==0)<br />break;<br />for(i=1; i<=n; i++)<br />scanf("%d",&key[i]);<br />memset(T,0,sizeof(T[0]));<br />fun();<br />while(scanf("%d",&k) && k)<br />{<br />getchar();<br />gets(str+1);//讀入字串,注意座標從1開始;目的是忽略k後面的一個空格;<br />len = strlen(str+1);<br />/*while(len<=n)//補充空格<br />{<br />str[++len] = ' ';<br />}*/<br />for(i=len+1; i<=n; i++)//補充空格<br />str[i] = ' ';<br />str[n+1] = '/0'; //注意;<br />for(i=1; i<=n; i++)<br />{<br />pos = i;<br />for(j=0; j<k%T[i]; j++)//k%T[i]處理後結果位置一樣,模運算表明:加速,要是不%T[i],就會逾時。<br />pos = key[pos];//就是k%T[i]次加密後,字元i的最終位置,如1->4->7->1,這裡就是7;<br />ch[pos] = str[i];//把字元i放到最終的位置上;<br />//cout<<str[i]<<" "<<pos<<" "<<i<<endl;<br />}<br />ch[n+1] ='/0';//千萬要注意;<br />printf("%s/n",ch+1);<br />//puts(ch+1);<br />}<br />printf("/n");<br />}<br />return 0;<br />}