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

 

 

posted on 2008-09-05 02:02  woodfish  阅读(1309)  评论(1编辑  收藏  举报

导航