1. 程式人生 > 資訊 >雷神 911MR 遊戲本釋出:R7-5800H/RTX 3060,首發 6999 元

雷神 911MR 遊戲本釋出:R7-5800H/RTX 3060,首發 6999 元

 ·康託展開:
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>
 4
using 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 long
long 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 }