POJ 3590 The shuffle Problem(置换+DP)

The shuffle Problem
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 2173 Accepted: 723

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
The 1st shuffle:5, 3, 2, 1, 4
The 2nd shuffle:4, 2, 3, 5, 1
The 3rd shuffle:1, 3, 2, 4, 5
The 4th shuffle:5, 2, 3, 1, 4
The 5th shuffle:4, 3, 2, 5, 1
The 6th shuffle:1, 2, 3, 4, 5(the same as it is in the beginning)

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]

Home Page   Go Back  To top


题意:给你一个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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值