PKU 1026 Cipher
各文字は一定の周期で移動する。サンプルインプットの (4 5 3 7 2 8 1 6 10 9) ならば、
1,4,7 は 1→4→7→1 と周期3で
2,5 は 2→5→2 と周期2で巡回する。
kを周期で割った余りだけ動かして計算時間を短縮する。時間制限がけっこう厳しい。
#include <stdio.h> #include <string.h> int main() { int n, k, a[200]; char m[201], c[201]; // c[v[i][k%vn]] = m[i] となるようなテーブル作成 int v[200][256]; int vn[200] = { 0 }; while ( true ) { scanf( "%d", &n ); if ( n == 0 ) break; for ( int i=0; i<n; i++ ) scanf( "%d", &a[i] ), a[i]--; for ( int i=0; i<n; i++ ) { v[i][0] = i; vn[i] = 0; do v[i][vn[i]+1] = a[ v[i][vn[i]] ], vn[i]++; while ( v[i][vn[i]] != i ); } while ( true ) { scanf( "%d", &k ); if ( k == 0 ) break; getchar(); gets( m ); for ( int i=(int)strlen(m); i<n; i++ ) m[i] = ' '; m[n] = '\0'; for ( int i=0; i<n; i++ ) c[ v[i][k%vn[i]] ] = m[i]; c[n] = '\0'; puts( c ); } puts( "" ); } return 0; }
GCC 281B。元が長いとあまり楽しくないことに気付いた。
main(n,d,i,k,t,j) { int N=256,a[N],v[N]; char m[N],c[N]; for(;scanf(d="%d",&n),n;puts("")) { for(i=0;i<n;scanf(d,a+ ++i)); for(;i;i--)for(v[t=i]=1;t=a[t],t-i;v[i]++); for(;scanf(d,&k),k;c[n+1]=0,puts(c+1)) for(i=1,gets(m);i<=n;c[t]=!m[i]?m[i+1]=0,32:m[i],i++) for(j=k%v[i],t=i;j--;t=a[t]); } }