POJ

来源:互联网 发布:韩语入门教材知乎 编辑:程序博客网 时间:2024/06/05 06:29

根据置换群的基本知识知道,一个置换P,对于P^k=P的最小k,其实等于P所有循环大小的LCM

所以问题转化为给你一个数n,将它分为几个数,使得和为n,并且LCM最大

很显然和最终的数中的每个素数因子的次数有关,

我们设dp[i][j],和小于等于i的数,现在考虑到了第j个素数的最大LCM是多少

就是可以写DP了


还有一题加强版的是:http://www.lydsy.com/JudgeOnline/problem.php?id=1025

#include<iostream>#include<cstdio>#include<math.h>#include<algorithm>#include<map>#include<set>#include<bitset>#include<stack>#include<queue>#include<string.h>#include<string>#include<cstring>#include<vector>#include<time.h>#include<stdlib.h>using namespace std;#define INF 0x3f3f3f3f#define INFLL 0x3f3f3f3f3f3f3f3f#define FIN freopen("input.txt","r",stdin)#define mem(x,y) memset(x,y,sizeof(x))typedef unsigned long long ULL;typedef long long LL;#define fuck(x) cout<<x<<endl;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef pair<pair<int,int>,int> PIII;typedef pair<int,int> PII;const double eps=1e-5;const int P=1e9+7;const int MX=1e2+5;int n,k;int prime[MX];int dp[MX][MX];int path[MX][MX];int main(){    prime[0]=0;    for(int i=2; i<MX; i++)    {        int flag=0;        for(int j=2; j<i; j++)            if(i%j==0)flag=1;        if(flag==0)prime[++prime[0]]=i;    }    for(int i=0; i<MX; i++)    {        dp[i][0]=1;        dp[0][i]=1;    }    for(int i=1; i<MX; i++)    {        int maxn=0;        for(int j=1; j<=prime[0]; j++)        {            dp[i][j]=dp[i][j-1];            path[i][j]=0;            int now=prime[j];            while(now<=i)            {                if(dp[i-now][j-1]*now>dp[i][j])                {                    dp[i][j]=dp[i-now][j-1]*now;                    path[i][j]=now;                }                now*=prime[j];            }            // cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;        }    }    int m=27;    FIN;    int T;    cin>>T;    while(T--)    {        scanf("%d",&n);        printf("%d ",dp[n][m]);        int ans=0;        int now=path[n][m],x=n,y=m;        vector<int>w;        while(x&&y)        {           // cout<<x<<" "<<y<<" "<<now<<endl;            if(now)w.push_back(now);            ans+=now;            x=x-now;            y--;            now=path[x][y];        }        for(int i=ans+1; i<=n; i++)w.push_back(1);        sort(w.begin(),w.end());        int up=w.size();        int tot=1;        for(int i=0; i<up; i++)        {            //cout<<w[i]<<endl;            for(int j=tot+1; j<=tot+w[i]-1; j++)            {                printf("%d ",j);            }            printf("%d%c",tot,i==up-1?'\n':' ');            tot= tot+w[i];        }    }    return 0;}


原创粉丝点击