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

 

 

你可能感兴趣的:(poj)