【思路】
利用杨辉三角形,每一个数字被加的次数等于它在杨辉三角形中对应的那个数字。注意这道题的意思是,最底层是N的全排序,而不是指1..10都可以。生成杨辉三角形的时候第一次我用了二重循环模拟生成,后来学习到,杨辉三角形中,第n行第k个数字为Cnk。不过在第二个程序中我的杨辉三角形没有预处理,导致了很多时间的浪费。用了深搜和STL两种方法。深搜因为能够剪枝所以明显要比Next_permuation快。
1 /*232K 0MS*/ 2 /*模拟+深搜*/ 3 #include<iostream> 4 #include<cstdio> 5 using namespace std; 6 const int MAXN=10+5; 7 int n,sum; 8 int a[MAXN][MAXN]; 9 int ans[MAXN]; 10 int vis[MAXN]; 11 int f; 12 13 void gettri() 14 { 15 for (int i=0;i<n;i++) 16 { 17 a[i][0]=1; 18 a[i][i]=1; 19 } 20 for (int i=2;i<n;i++) 21 for (int j=1;j<i;j++) 22 a[i][j]=a[i-1][j-1]+a[i-1][j]; 23 } 24 25 void print() 26 { 27 for (int i=0;i<n;i++) cout<<ans[i]<<' '; 28 cout<<endl; 29 } 30 31 void getnum(int step,int nowsum) 32 { 33 if (step==n) 34 { 35 if (nowsum==sum) 36 { 37 f=1; 38 printf(); 39 } 40 return; 41 } 42 if (f||nowsum>sum) return; 43 for (int i=1;i<=n;i++) 44 { 45 if (vis[i]==1) continue; 46 vis[i]=1; 47 ans[step]=i; 48 getnum(step+1,nowsum+i*a[n-1][step]); 49 vis[i]=0; 50 } 51 } 52 53 int main() 54 { 55 scanf("%d%d",&n,&sum); 56 gettri(); 57 58 memset(vis,0,sizeof(vis)); 59 f=0; 60 getnum(0,0); 61 return 0; 62 }
1 /*232K 469MS*/ 2 /*组合+STL*/ 3 #include<iostream> 4 #include<cstdio> 5 #include<cstring> 6 #include<algorithm> 7 using namespace std; 8 const int MAXN=10+3; 9 int n,sum; 10 int ans[MAXN]; 11 12 int c(int n,int k) 13 { 14 int cresult=1; 15 for (int i=0;i<k;i++) cresult=cresult*(n-i)/(i+1); 16 //这里不能写成cresult=cresult*(n-i)/(k-i),因为如果从大到小可能无法整除,精确度会导致错误 17 return cresult; 18 } 19 20 int main() 21 { 22 scanf("%d%d",&n,&sum); 23 for (int i=0;i<n;i++) ans[i]=i+1; 24 do 25 { 26 int result=0; 27 for (int i=0;i<n;i++) result+=ans[i]*c(n-1,i); 28 if (result==sum) 29 { 30 for (int i=0;i<n;i++) cout<<ans[i]<<' '; 31 cout<<endl; 32 break; 33 } 34 }while (next_permutation(ans,ans+n)); 35 return 0; 36 }