首页 > 代码库 > poj 3590 The shuffle Problem(置换群+DP)

poj 3590 The shuffle Problem(置换群+DP)

题目链接:poj 3590 The shuffle Problem

题意:

给你一个数n,让你找一个字典序最小的置换序列,使得变换整个周期最大。

题解:

由于置换群的性质,我们可以将n拆分成m个数,使得这m个数的和为n,并且这m个数的最小公倍数最大。

dp可以求出将n拆分后的最大的最小公倍数。

然后可以将这个最大的最小公倍数分解为pi^mi+pi^mi+pi^mi...。

对于每一个pi^mi,就是一个循环的轮数。

然后将这些循环的轮数排序后输出对于的数字就行了。

PS:当前面的总和sum小于n时,前n-sum的循环轮数就全是1,这些数不会影响最大的最小公倍数。

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define F(i,a,b) for(int i=a;i<=b;++i)
 5 using namespace std;
 6 typedef long long ll;
 7 
 8 const int N=101;
 9 
10 int primes[N+1],tot=0;
11 bool vis[N+1];
12 void Euler(){
13     memset(vis,0,sizeof(vis));
14     F(i,2,N){
15         if(!vis[i])primes[++tot]=i;
16         F(j,1,tot){
17             if(i*primes[j]>N)break;
18             vis[i*primes[j]]=1;
19             if(i%primes[j]==0)break;
20         }
21     }
22 }
23 
24 int dp[N][N],mx[N],cnt,tmp,t,sum,n,ans[N];
25 
26 void init()
27 {
28     F(i,1,100)F(j,1,100)dp[i][1]=i;
29     F(i,1,100)
30     {
31         F(j,1,i)
32         {
33             F(k,1,i-1)
34             {
35                 int tmp=dp[i-k][j-1]*k/__gcd(dp[i-k][j-1],k);
36                 if(dp[i][j]<tmp)dp[i][j]=tmp;
37             }
38         }
39         F(j,1,i)mx[i]=max(dp[i][j],mx[i]);
40     }
41 }
42 
43 int main()
44 {
45     Euler(),init();
46     scanf("%d",&t);
47     while(t--)
48     {
49         scanf("%d",&n);
50         tmp=mx[n],sum=cnt=0;
51         printf("%d",mx[n]);
52         int tmp=mx[n],tp;
53         F(i,1,25)
54         {
55             if(primes[i]>tmp)break;
56             if(tmp%primes[i]==0)
57             {
58                 tp=1;
59                 while(tmp%primes[i]==0)tmp/=primes[i],tp*=primes[i];
60                 ans[++cnt]=tp,sum+=tp;
61             }
62         }
63         sort(ans+1,ans+1+cnt);
64         F(i,1,n-sum)printf(" %d",i);
65         int now=1,num=ans[now],ct=0;
66         F(i,n-sum+1,n)
67         {
68             if(ct==num-1)
69                 printf(" %d",i-ct),ct=0,num=ans[++now];
70             else printf(" %d",i+1),ct++;
71         }
72         puts("");
73     }
74     return 0;
75 }
View Code

 

poj 3590 The shuffle Problem(置换群+DP)