1 12 12 22 32 43 10Sample Output111 222 12 3 1我的思路 : 看了標準代碼懵逼好久最終搞定。按照數字大小順序排序,
可以發現,輸出的序列第一個是m除以n個數的排序數,比如2有2種組合,3每次有5種組合,如果組合數以數組a(n)表示,則有a(n)=(n-1)*a(n-1)+1的規律
剩下的依序輸出,比如輸入的n和m是3 10,則第一個輸出的應當是10/5,考慮到3有5種組合,但是第五種是以1開頭的最后一種序列,所以,m=10時,其實是2開頭的最后一種序列。若是m=11,雖然m/5=2,但是已經是3開頭的序列了,所以,計算第一個輸出的數時,應該是t=m/n組合數+m%n組合數?1:0;意思是如果求余不為0,加一,這樣就符合實際情況。以此類推,每當輸出一個t,應當將t從常數數組內去除,也就是將t之后的數全部提前一位。
以下是我的代碼:#include<iostream>#include<stdio.h>#include<algorithm>#include<cmath>#include<iomanip>#include<string.h>using namespace std;int main( ){ int a[21] = {0}, i; long long p[21] = {0}, n, m, t; while (cin >> n >> m) { for (i = 0; i < 21; i++) a[i] = i; p[1] = 1; for (i = 2; i < 21; i++) p[i] = p[i-1] * (i - 1) + 1; //計算出每個數字有幾種排列,如N=1時,數字1開頭有1種排列; //N=2時,數字1開頭有2種排列;N=3時, 有5種排列。 while (n-- && m) { t = m / p[n+1] + (m % p[n+1] ? 1 : 0); //計算出該m是在哪一組 cout << a[t]; for (i = t; i <= n; i++) a[i] = a[i+1];//刪去已經排列那個數字 m = m - ((t - 1) * p[n + 1] + 1); // 去掉前面的小于t開頭的組合,且將去掉一個僅有t的集合 if (m==0) cout << "/n"; else cout << " "; } } return 0;}
新聞熱點
疑難解答