【佛山市選2013】2020年8月7日T4 排列
阿新 • • 發佈:2020-08-08
【佛山市選2013】2020年8月7日T4 排列
題目
描述
一個關於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。
資料
對於40%的資料,有1≤N≤100。
對於所有的資料,有1≤N≤10000。
題解
題意
簡化一下
給出\(n\)
讓你生成一些環
要求環的總大小是\(n\)並使每個環的大小的最小公倍數最大
多組資料
分析
最小公倍數最大
那麼每個環的大小兩兩互質肯定是最優的
最小公倍數即可表示成\(p1^{x1}*p2^{x2}*……*pn^{xn}\)
那麼呢
設\(f[i][j]\)表示選了\(i\)個質數和為\(j\)的最大秩
然後對於第\(i\)個質數暴力列舉取多少次方
記個前驅來生成序列
完事
Code
#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; int t,n,i,j,ii,mx,num,x,sum,ansnum,last,p[2005],a[10005],g[2005][10005],ans1[10005],ss[10005]; bool b[10005]; double add,m,lg,f[2005][10005]; int main() { freopen("T4.in","r",stdin); freopen("T4.out","w",stdout); scanf("%d",&t); for (i=1;i<=t;i++) { scanf("%d",&a[i]); mx=max(mx,a[i]); } for (i=2;i<=mx;i++) for (j=2;i*j<=mx;j++) b[i*j]=true; for (i=2;i<=mx;i++) if (b[i]==false) { num++; p[num]=i; } for (i=0;i<num;i++) for (j=0;j<=mx;j++) { if (f[i][j]>f[i+1][j]) { f[i+1][j]=f[i][j]; g[i+1][j]=j; } x=p[i+1]; lg=log(x); for (add=lg;x+j<=mx;x*=p[i+1],add+=lg) { if (f[i][j]+add>=f[i+1][x+j]) { f[i+1][x+j]=f[i][j]+add; g[i+1][x+j]=j; } } } for (ii=1;ii<=t;ii++) { n=a[ii]; if (n==1) { printf("1\n"); continue; } m=0; sum=n; ansnum=0; for (i=1;i<=n;i++) { if (f[num][i]>m) { m=f[num][i]; x=i; } } for (i=1;i<=n-x;i++) { ansnum++; ans1[ansnum]=1; } i=num; while (i) { ansnum++; ans1[ansnum]=x-g[i][x]; x=g[i][x]; i--; } sort(ans1+1,ans1+ansnum+1); last=0; x=1; while (ans1[x]==0&&x<=num) x++; for (i=1;i<=n;i++) { if (i==last+ans1[x]) { ss[i]=last+1; last+=ans1[x]; x++; } else ss[i]=i+1; } for (i=1;i<=n;i++) printf("%d ",ss[i]); printf("\n"); } fclose(stdin); fclose(stdout); return 0; }