The shuffle Problem
Description Any case of shuffling of n cards can be described with a permutation of 1 to n. Thus there are totally n! cases of shuffling. Now suppose there are 5 cards, and a case of shuffle is <5, 3, 2, 1, 4>, then the shuffle will be: Before shuffling:1, 2, 3, 4, 5 You'll find that after six shuffles, the cards' order returns the beginning. In fact, there is always a number m for any case of shuffling that the cards' order returns the beginning after m shuffles. Now your task is to find the shuffle with the largest m. If there is not only one, sort out the one with the smallest order. Input The first line of the input is an integer T which indicates the number of test cases. Each test case occupies a line, contains an integer n (1 ≤ n ≤ 100). Output Each test case takes a line, with an integer m in the head, following the case of shuffling. Sample Input 2 1 5 Sample Output 1 1 6 2 1 4 5 3 Source |
[Submit] [Go Back] [Status] [Discuss]
题意:给你一个n,让你找一个n阶置换,使得置换的字典序最小,且置换的次数尽可能的多。
题解:我们知道,置换是由若干个循环节构成,每个循环节的长度的最小公倍数便是总的置换次数。
并且所有的循环节长度之和为n,呢么题目其实就是让我们找到若干个数x1.....xm使得:
x1+x2+....xm=n && lcm(x1,x2....xm)最大。
对于求最大的lcm,我们考虑dp即可。剩下的循环节直接模拟贪心找就好。
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<time.h>
#include<math.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<functional>
using namespace std;
#define ll long long
#define inf 1000000000
#define mod 1000000007
#define maxn 30
#define lowbit(x) (x&-x)
#define eps 1e-9
ll dp[105],c[105];
int a[105]={1,1},b[50],ans[105],cnt;
void init()
{
int i,j;
for(i=2;i<=100;i++)
{
if(a[i])
continue;
b[++cnt]=i;
for(j=i*i;j<=100;j+=i)
a[j]=1;
}
}
int q(int x,int y)
{
int res=1;
while(y)
{
if(y%2)
res=res*x;
x=x*x;
y/=2;
}
return res;
}
int main(void)
{
init();
int T,n,i,j,k;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=0;i<=100;i++)
dp[i]=1,ans[i]=1;
for(i=1;i<=cnt;i++)
{
for(j=0;j<=n;j++)
c[j]=dp[j];
for(j=1;q(b[i],j)<=n;j++)
{
ll tmp=q(b[i],j);
for(k=tmp;k<=n;k++)
dp[k]=max(dp[k],c[k-tmp]*tmp);
}
}
printf("%lld",dp[n]);
int sum=0,num=0;
ll mx=dp[n];
for(i=1;i<=cnt;i++)
{
int flag=0;
while(mx%b[i]==0)
{
flag=1;
mx/=b[i];
ans[num]*=b[i];
}
if(flag)
{
sum+=ans[num];
num++;
}
}
sort(ans,ans+num);
for(i=1;i<=n-sum;i++)
printf(" %d",i);
int len=n-sum;
for(i=0;i<num;i++)
{
for(j=2;j<=ans[i];j++)
printf(" %d",len+j);
printf(" %d",len+1);
len+=ans[i];
}
printf("\n");
}
return 0;
}