POJ 1026 置换群的k次幂问题

题目大意:

给定了一组对应关系,经过k次幂后,得到新的对应关系b[i],然后将给定的字符串上的第i位字符放置到b[i]的位置上,

如果字符串长度不足n就用空格补足,这里的是空格,也就是str[i] = ' ',不是str[i]='\0' ,自己这里错了好几回就是找不到问题,看了别人代码才明白

 

置换群的k次幂问题不清楚,可以看看<<置换群快速幂运算+研究与探讨.pdf>>

这里初始给定的置换群要注意这个群不一定是一个循环集,我们要先统计出它的每一个循环集,然后每一个分别进行操作计算

 

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <iostream>

 4 using namespace std;

 5 const int N = 205;

 6 //qun[i]保存第i个循环集的第一个数,a[]表示原映射,b[]表示k次幂后得到的新的对应关系,cnt表示循环集的个数

 7 int a[N] , b[N] , tmp[N] , tmp_new[N] , qun[N] , vis[N] , cnt;

 8 char str[N];

 9 

10 void circle(int u)

11 {

12     qun[cnt] = u;

13     int v = u;

14     while(u != a[v]){

15         vis[v] = 1;

16         v = a[v];

17     }

18     vis[v] = 1;

19     cnt++;

20 }

21 //返回当前循环集的长度

22 int get_tmp(int cnt)

23 {

24     int index = 0;

25     tmp[index++] = qun[cnt];

26    // cout<<"here: "<<cnt<<" start: "<<qun[cnt]<<endl;

27     int u = a[qun[cnt]];

28     while(u != tmp[0]){

29         tmp[index++] = u;

30         u = a[u];

31     }

32     return index;

33 }

34 

35 int main()

36 {

37    // freopen("a.in" , "r" , stdin);

38     int n , k;

39     while(scanf("%d" , &n) , n)

40     {

41         for(int i=1 ; i<=n ; i++)

42             scanf("%d" , a+i);

43 

44         memset(vis , 0 ,sizeof(vis));

45         cnt = 0;

46         //初始置换群中可能有多个循环集,我们需要一个一个循环集进行操作

47         for(int i=1 ; i<=n ; i++)

48             if(!vis[i]) circle(i);

49 

50         while(scanf("%d" , &k) , k){

51             getchar();

52             gets(str+1);

53             int len = strlen(str+1);

54             for(int i=len+1 ; i<=n ; i++)

55                 str[i] = ' ';

56            // printf("%s\n" , str+1);

57             for(int i=0 ; i<cnt ; i++){

58                 int len = get_tmp(i);

59 

60                 int index = 0 , pos = 0;

61                 tmp_new[index++] = tmp[0];

62 

63                 memset(vis , 0 , sizeof(vis));

64                 vis[0] = 1;

65                 for(int i=1 ; i<len ; i++){

66                     pos = (pos+k)%len;

67                     //分裂成了一个小循环集

68                     if(vis[pos]){

69                         for(int i=0; i<index ; i++){

70                             if(i <index-1) b[tmp_new[i]] = tmp_new[i+1];

71                             else b[tmp_new[i]] = tmp_new[0];

72                         }

73                         //tmp数组下标清零

74                         index = 0;

75                         pos = (pos+1)%len;

76                     }

77                     tmp_new[index++] = tmp[pos];

78                     vis[pos] = 1;

79                 }

80                 //最后一个分裂出来的循环集的映射加入到b中

81                 for(int i=0; i<index ; i++){

82                     if(i <index-1) b[tmp_new[i]] = tmp_new[i+1];

83                     else b[tmp_new[i]] = tmp_new[0];

84                 }

85             }

86 

87             char ans[N];

88             for(int i=1 ; i<=n ; i++){

89                 ans[b[i]] = str[i];

90             }

91             ans[n+1] = '\0';

92             printf("%s\n" , ans+1);

93         }

94         puts("");

95     }

96     return 0;

97 }

 

你可能感兴趣的:(poj)