POJ 1026 置换群
http://acm.pku.edu.cn/JudgeOnline/problem?id=1026
如果按照题意,直接模拟,由于题目中没有给k的范围,有可能超时,其实数据中都是k非常大,所以这种算法行不通。
每一次操作相当于对序列进行一次置换,由置换群的知识可知,如该置换的阶为kk,则进行k次置换的结果与进行k%kk次置换的结果相同,因此可以先求出置换群的阶。
如果对于序列中的每个元素分别求出循环阶数,然后再求所有这些结束的最小公倍数得到整个置换群的阶,这个阶任然有可能很大,超时。
换一种思路,由于进行k次置换,而每个元素的置换可以看成是独立的,即元素i进行k次置换后会到达Pi位置。因此我们单独对每个元素进行置换,求出每个元素的阶ki(<=n),然后进行k%ki次置换求出最后i元素到达的位置Pi即可。这样算法的时间复杂度是O(n^2).
//置换群
#include <stdio.h>
#include <string.h>
char buf[201],buf2[201],buf3[201];
int a[201];
int getm(int i) {
int ret=1;
int now=a[i]-1;
while(now!=i) {
ret++;
now=a[now]-1;
}
return ret;
}
int main() {
int n,k;
char space;
while(scanf("%d\n",&n)!=EOF&&n) {
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
scanf("\n");
while(scanf("%d",&k)!=EOF){
if(k==0) {
scanf("\n");
break;
}
scanf("%c",&space);
gets(buf);
int len=strlen(buf);
if(buf[len-1]=='\r') buf[len--]=0;
for(int i=0;i<n-len;i++) buf[len+i]=' ';
memset(buf2,0,sizeof(buf2));
for(int i=0;i<n;i++) {
int m=getm(i);
int kk=k%m;
int now=i;
while(kk--) {
now=a[now]-1;
}
buf2[now]=buf[i];
}
printf("%s\n",buf2);
}
putchar('\n');
}
return 0;
}
#include <stdio.h>
#include <string.h>
char buf[201],buf2[201],buf3[201];
int a[201];
int getm(int i) {
int ret=1;
int now=a[i]-1;
while(now!=i) {
ret++;
now=a[now]-1;
}
return ret;
}
int main() {
int n,k;
char space;
while(scanf("%d\n",&n)!=EOF&&n) {
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
scanf("\n");
while(scanf("%d",&k)!=EOF){
if(k==0) {
scanf("\n");
break;
}
scanf("%c",&space);
gets(buf);
int len=strlen(buf);
if(buf[len-1]=='\r') buf[len--]=0;
for(int i=0;i<n-len;i++) buf[len+i]=' ';
memset(buf2,0,sizeof(buf2));
for(int i=0;i<n;i++) {
int m=getm(i);
int kk=k%m;
int now=i;
while(kk--) {
now=a[now]-1;
}
buf2[now]=buf[i];
}
printf("%s\n",buf2);
}
putchar('\n');
}
return 0;
}