博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[背包]JZOJ 3232 【佛山市选2013】排列
阅读量:7167 次
发布时间:2019-06-29

本文共 2285 字,大约阅读时间需要 7 分钟。

Description

一个关于n个元素的排列是指一个从{1, 2, …, n}到{1, 2, …, n}的一一映射的函数。这个排列p的秩是指最小的k,使得对于所有的i = 1, 2, …, n,都有p(p(…p(i)…)) = i(其中,p一共出现了k次)。
例如,对于一个三个元素的排列p(1) = 3, p(2) = 2, p(3) = 1,它的秩是2,因为p(p(1)) = 1, p(p(2)) = 2, p(p(3)) = 3。
给定一个n,我们希望从n!个排列中,找出一个拥有最大秩的排列。例如,对于n=5,它能达到最大秩为6,这个排列是p(1) = 4, p(2) = 5, p(3) = 2, p(4) = 1, p(5) = 3。
当我们有多个排列能得到这个最大的秩的时候,我们希望你求出字典序最小的那个排列。对于n个元素的排列,排列p的字典序比排列r小的意思是:存在一个整数i,使得对于所有j < i,都有p(j) = r(j),同时p(i) < r(i)。对于5来说,秩最大而且字典序最小的排列为:p(1) = 2, p(2) = 1, p(3) = 4, p(4) = 5, p(5) = 3。
 

Input

输入的第一行是一个整数T(T <= 10),代表数据的个数。
每个数据只有一行,为一个整数N。

Output

对于每个N,输出秩最大且字典序最小的那个排列。即输出p(1), p(2),…,p(n)的值,用空格分隔。
 

Sample Input

2 5 14

Sample Output

2 1 4 5 3 2 3 1 5 6 7 4 9 10 11 12 13 14 8
 

Data Constraint

对于40%的数据,有1≤N≤100。
对于所有的数据,有1≤N≤10000。

分析

稍作分析就可以发现这是要把一个正整数分为多个正整数,其最小公倍数最大的正整数组的最小字典序

考虑到排列很难构造,那我们直接构造最小公倍数

它必定是若干个质数的乘积

那么题中的最小公倍数则可以表示为

W=p1^c1*p2^c2*p3^c3…… p是质数 c是质数的指数,p之和不超过n

如果比n小怎么办?直接在排列最前端补足1 2 3 4 5 6……

那么可得f[i][j]为处理了第i个质数,和为j的最大最小公倍数(因为是质数直接乘)

f[i][j]=f[i-1][j-w]*w w为质数或质数的幂

至于答案,只需要用g[i][j]记录一下状态是从哪个状态转移过来的即可

注意,f的值会非常大,可以用自然对数法,也可以直接用double(本题几乎无视精度问题)

 

#include 
#include
#include
using namespace std;typedef double ld;const int N=1e4+10;int prime[1310],cnt;bool b[N];int t,n;int from[1310][N],cunt,a[1310],acnt;ld f[1310][N],mx; void Get_Prime() { for (int i=2;i<=10000;i++) { if (!b[i]) prime[++cnt]=i; int j=2*i; while (j<=10000) { b[j]=1; j+=i; } }}void Get(int last) { int dep=cnt; while (dep) { if (last-from[dep][last]) a[++acnt]=last-from[dep][last]; last=from[dep][last];dep--; }}int main() { Get_Prime(); for (scanf("%d",&t);t;t--) { scanf("%d",&n); if (n<5) { for (int i=2;i<=n;i++) printf("%d ",i); printf("1\n"); continue; } mx=0; for (int i=1;i<=cnt;i++) for (int j=0;j<=n;j++) f[i][j]=0; f[0][0]=1; for (int i=1;i<=cnt;i++) { int l=prime[i]; for (int j=0;j<=n;j++) f[i][j]=f[i-1][j],from[i][j]=j; for (;l<=n;l*=prime[i]) { for (int j=l;j<=n;j++) if (f[i][j]
View Code

 

转载于:https://www.cnblogs.com/mastervan/p/11107804.html

你可能感兴趣的文章
ARM-Linux配置DHCP自动获取IP地址
查看>>
文本框改变事件(不用失去焦点)
查看>>
【求助】怎样实如今并肩看中增加代码啊
查看>>
mysql 性能优化方案
查看>>
Java并发编程:volatile关键字解析
查看>>
Oracle Alert - APP-ALR-04108: SQL error ORA-01455
查看>>
【转】在linux内核中读写文件 -- 不错
查看>>
http put post请求区别
查看>>
android EventBus的简单使用
查看>>
在.net中使用GAC
查看>>
EasyExcel导入工具(SpringMVC下使用)
查看>>
【转载】查找怪数据数组的内存分布和地址(天龙八部)
查看>>
敏捷生活练习第14次活动:学会感恩
查看>>
Windows Azure Cloud Service (15) 多个VM Instance场景下如何处理ASP.NET Session
查看>>
Android学习笔记(7)————Android中的消息机制
查看>>
重装系统后,硬盘分区丢失的解决办法
查看>>
玩转轻巧型C/C++ IDE之C-Free(配置GCC、Visual C++、Borland C++编译器)
查看>>
利用Delphi编写IE扩展
查看>>
邮箱里边添加自己的网站首页
查看>>
zdnet网站上关注MS技术的记者Foley
查看>>