FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N <= 10) in a certain order and then sum adjacent numbers to produce a new list with one fewer number. They repeat this until only a single number is left. For example, one instance of the game (when N=4) might go like this:
Write a program to help FJ play the game and keep up with the cows.
3 1 2 4Behind FJ's back, the cows have started playing a more difficult game, in which they try to determine the starting sequence from only the final total and the number N. Unfortunately, the game is a bit above FJ's mental arithmetic capabilities.
4 3 6
7 9
16
Write a program to help FJ play the game and keep up with the cows.
Input
Line 1: Two space-separated integers: N and the final sum.
Output
Line 1: An ordering of the integers 1..N that leads to the given sum. If there are multiple solutions, choose the one that is lexicographically least, i.e., that puts smaller numbers first.
Sample Input
4 16
Sample Output
3 1 2 4
Hint
Explanation of the sample:
There are other possible sequences, such as 3 2 1 4, but 3 1 2 4 is the lexicographically smallest.
There are other possible sequences, such as 3 2 1 4, but 3 1 2 4 is the lexicographically smallest.
这个题竟然是深搜,看得题目中说用全排列字典序输出有点吓人...
我们先来看一下杨辉三角形的性质。第n行第m个数的值是C上m 下n-1 (组合数打不出来啊...),由于杨辉三角形的形成过程的逆过程。我们可以知道sum的最终和
sum=0 C n-1*ans[0]+1 C n-1*ans[1]+2 C n-1*ans[2]+3 C n-1*ans[3]+4 C n-1*ans[4]+......
好好理解这个逆过程因为杨辉三角形一开始都是用1加起来的,所以我们从底下往上加的时候,每个最底层的数在求和时算了多少次?那个次数就是底层数字对应杨辉三角形的值。
剩下的交给深搜了。
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 int a[15][15],n,sum,vis[15],ans[15]; 5 bool f; 6 void setnum ()//生成杨辉三角形 7 { 8 for (int i=0;i<n;++i) 9 { 10 a[i][0]=1; 11 a[i][i]=1; 12 } 13 for (int i=2;i<n;++i) 14 for (int j=1;j<i;++j) 15 a[i][j]=a[i-1][j-1]+a[i-1][j]; 16 } 17 void printAns () 18 { 19 for (int i=0;i<n;++i) 20 { 21 printf("%d",ans[i]); 22 if (i!=n-1) 23 printf(" "); 24 } 25 printf(" "); 26 } 27 void dfs (int nowsum,int step)//这样的搜索是刚好字典序的 28 { 29 if (step==n) 30 { 31 if (nowsum==sum) 32 { 33 f=true; 34 printAns(); 35 } 36 return ; 37 } 38 if (f||nowsum>sum) 39 return ; 40 for (int i=1;i<=n;++i) 41 { 42 if (vis[i]) 43 continue; 44 vis[i]=1; 45 ans[step]=i; 46 dfs(nowsum+i*a[n-1][step],step+1); 47 vis[i]=0;//每次搜完以后要清空状态 48 } 49 } 50 int main() 51 { 52 scanf("%d%d",&n,&sum); 53 setnum(); 54 f=false; 55 memset(vis,0,sizeof vis); 56 memset(ans,0,sizeof ans); 57 dfs(0,0); 58 return 0; 59 }