• 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
  • 相关阅读:
    Node.js配置And HelloWorld
    谷歌浏览器扩展插件
    C#异步编程简单的运用
    C#中的特性基本理解
    JavaScript 字符 &quot;转换
    IHttpModule
    LinqToXml
    C#使用ajaxForm进行上传图片
    python 中的 __getitem__, __iter__ 和__next__
    python中的装饰器
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7074305.html
Copyright © 2020-2023  润新知