题解 P5919
a326820068122c · · 题解
这题首先不难想到需要每个置换能形成环才能满足
然后 order 是所有环大小的 LCM。
令环的大小为
对于先考虑如何让一个固定的
由于是字典序,可以考虑贪心,首先对于一组数
很显然,一定存在一个最优解使所有
然后发现如果一个数
综上,
于是可以先筛出
然后进行带路径记录的分组背包(可以理解成对于每个质数
这里有两个小细节 :
一,可以采用 long double 来代替高精度,由于只需比较大小,不需输出,所以不需要那么高的精度(实测可以过)。
二,不难发现比较大的质数并不会被选中,我们可以先让程序用
最后放一下代码:
#include <bits/stdc++.h>
#define for1(i,n) for(i=1;i<=(n);i++)
#define forlr(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
typedef long double ld;
const int N=10005,D=10000;
int z[N],cz,n,pre[75][N],T,c[N],cc;
bool b[N];
ld dp[75][N];
int main(){
int i,j,k;
forlr(i,2,D){
if(!b[i]) z[++cz]=i;
if(cz==72) break;
for(j=1;z[j]*i<=D;j++){
b[z[j]*i]=1;
if(!(i%z[j])) break;
}
}
forlr(i,0,D) dp[0][i]=1;
for1(j,cz){
forlr(i,0,D) pre[j][i]=0,dp[j][i]=dp[j-1][i];
forlr(i,0,D) for(k=z[j];i+k<=D;k*=z[j]) if(dp[j][i+k]<dp[j-1][i]*k)
pre[j][i+k]=k,dp[j][i+k]=dp[j-1][i]*k;
}
scanf("%d",&T);
while(T--){
scanf("%d",&n);cc=0;
for(i=cz;i;i--) if(pre[i][n]) n-=(c[++cc]=pre[i][n]);
sort(c+1,c+cc+1);
for1(i,n) printf("%d ",i);
for1(j,cc){
forlr(k,i,i+c[j]-2) printf("%d ",k+1);
printf("%d ",i);i+=c[j];
}
puts("");
}
return 0;
}