题目链接:https://www.luogu.org/problemnew/show/P1118
题意:
1~n的一个排列,相邻的两项加起来得到下一行。
现在给定最后一行的数字,问最初的1~n的排列是什么。
思路:
next_permutation大法好。但是要注意剪枝。
首先要发现最后一行这个数系数的规律是一个杨辉三角。
先处理出这个系数。
然后排列。
如果我们在加到前i项的时候发现他已经比结果大了,那么后面不管怎么排列都是没有用的,要跳过。
怎么跳过呢,这里还挺tricky的【要学会!】
用sort对后面几个数从大到小排序就行了,因为本身next_permutation就是按照“字典序”来排的
这里要注意用的是do...while【竟然这年头还真有用do...while的】
因为不然第一个1234....n这个排列没有被考虑到。
#include<stdio.h>
#include<stdlib.h>
#include<map>
#include<set>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue> using namespace std;
typedef long long LL;
typedef pair<int, int> pr; int n, sum;
int num[];
int xishu[][]; bool cmp(int a, int b)
{
return a > b;
} int main()
{
// LL res = 1;
// for(int i = 1; i <= 12; i++){
// res *= i;
// }
// printf("%lld\n", res);
scanf("%d%d", &n, &sum);
for(int i = ; i <= n; i++){
num[i] = i;
}
xishu[][] = ;
for(int i = ; i <= n; i++){
for(int j = ; j <= i; j++){
xishu[i][j] = xishu[i - ][j - ] + xishu[i - ][j];
}
} do{
int ans = ;
bool flag = true;
for(int i = ; i <= n; i++){
ans += xishu[n][i] * num[i];
if(ans > sum){
flag = false;
sort(num + i, num + + n, cmp);
break;
}
}
if(ans == sum && flag){
printf("%d", num[]);
for(int i = ; i <= n; i++){
printf(" %d", num[i]);
}
printf("\n");
break;
}
}while(next_permutation(num + , num + + n)); return ;
}