Bob和Alice开始使用一种全新的编码方案。令人惊讶的是,这不是公共关键字密码系统,他们的编码和解码都是基于一种特殊的密码。他们于1996年2月16日在费城的最后一次会议上确定了他们的密码。他们把密码定为一个含有n个不同整数的数列,a1,…,an(0<ai<=n)。解码根据以下原则:把信息写在密钥的下方,使信息中的字符和密钥中的数字相应对齐。在位置i处的消息字符被写入位置ai处,其中ai是密钥中相应的编号。得到的消息以相同的方式继续被编码。重复这个过程k次,第k个编码即是最后答案。
消息的长度总是小于或等于n。若消息长度小于n,用空格补齐。
请你帮助Alice和Bob编写一个读取密钥的程序,进行k次编码,产生编码消息。
求出整个置换的循环节长度, 对于后面的每个询问, 都模循环节后暴力进行模拟.
时间复杂度 ,
上 ,
上 .
由于 整个置换 的循环节大小为 所有 子循环节 大小的 ,
导致时间复杂度为 , 其中 的上限为 , 在luogu竟然还能A.
但若求出每个位置单个的循环节, 对每个询问就可以 得到答案, 的上限为 .
求出整个置换的循环节大小需要 左右,
但是求出单个循环节大小仅需要 .
没什么好说的.
#include<cstdio>
#include<cstring>
#define reg register
const int maxn = 205;
int N;
int K;
int A[maxn];
int B[maxn];
int l[maxn];
char S[maxn];
char Ans[maxn];
void Work(){
getchar();
scanf("%[^
]", S+1);
int len = strlen(S+1);
while(len < N) S[++ len] = ' ';
for(reg int i = 1; i <= N; i ++) B[i] = i;
for(reg int i = 1; i <= N; i ++){
int tmp = K % l[i];
while(tmp --) B[i] = A[B[i]];
}
for(reg int i = 1; i <= N; i ++) Ans[B[i]] = S[i];
for(reg int i = 1; i <= N; i ++) printf("%c", Ans[i]);
printf("
");
}
int main(){
while(~scanf("%d", &N) && N){
for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]);
for(reg int i = 1; i<= N; i ++){
int t = i, to = A[i]; l[i] = 1;
while(to != t) l[i] ++, to = A[to];
}
while(~scanf("%d", &K) && K) Work();
printf("
");
}
return 0;
}