PKU 1026 Cipher

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