甜甜圈品牌與微軟聯動 推出《光環》和Xbox標誌甜甜圈
阿新 • • 發佈:2021-07-28
·康託展開: 1.先算 1~n 的階乘 jc[1]~jc[n] 2.計算每一位後面有幾個比這一位小的數 , 記為 num[i] 3.公式: ans+=num[i]*jc[n-i] ( i : 1~n ) < ※ans+1※ 即為 該展開式為全排列中的第幾個 > ·康託逆展開: 1.先算 1~n 的階乘 jc[1]~jc[n] 2.※ m-- ※ ( 因為算康託展開時最後要加1,所以先減1 ) 3.把m不斷除 jc[n-i] 得商和餘數 , 商就是這位後面比他小的數,再刨去前面已用過的,就是這個數 e.g.: 1 3 4 5 2 為5的全排列 中的第10種 10-1=9 ;9/(4!)=0……9; -> 第一位後面沒有比他小的數 ->1 9/(3!)=1……3; -> 第二位後面有一個比他小的數 , 1用過 ->3 3/(2!)=1……1; -> 第三位後面有一個比他小的數 , 1,3用過 ->4 3/(2!)=1……1; -> 第四位後面有一個比他小的數 , 1,3,4用過 ->5 3/(2!)=1……1; -> 第五位後面沒有比他小的數 , 1用過 ->2
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdio> 4using namespace std; 5 long long n,m,jc[101]; 6 bool vis[101]; 7 int main() 8 { 9 scanf("%lld%lld",&n,&m); 10 m--; //排列從1開始,從0開始沒這事 11 jc[0]=1; 12 jc[1]=1; 13 for(long long i=2;i<=n;++i) 14 jc[i]=jc[i-1]*i; 15 for(long long i=1;i<=n;++i) 16 { 17 longlong li=1,lj; 18 lj=m/jc[n-i]; 19 m-=lj*jc[n-i]; 20 while(vis[li]==true) 21 li++; 22 while(lj>0) 23 { 24 if(vis[li+1]==false) 25 lj--; 26 li++; 27 } 28 vis[li]=true; 29 printf("%lld ",li); 30 } 31 printf("\n"); 32 return 0; 33 }
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 long long n,ans,a[101],num[101],jc[101]; 5 int main() 6 { 7 scanf("%lld",&n); 8 jc[1]=1; 9 for(int i=2;i<=n;++i) 10 jc[i]=jc[i-1]*i; 11 for(int i=1;i<=n;++i) 12 scanf("%lld",&a[i]); 13 for(int i=1;i<=n;++i) 14 { 15 for(int j=i+1;j<=n;++j) 16 if(a[j]<a[i]) 17 num[i]++; 18 ans+=num[i]*jc[n-i]; 19 } 20 printf("%lld\n",ans+1); 21 return 0; 22 }