题目链接:https://www.luogu.com.cn/problem/P1118
思路:
首先根据每个数字出现的次数就是杨辉三角上的值,所以ans = ∑(numi×i)。
然后搜索,最先搜出的ai序列即是结果,然后输出就好了。
注意减枝,记录当前出现的编号之和为tp,当前求出的结果为sm,1~n之和为pp,如果pp-tp > sum - sm就不行直接返回。
(杨辉三角太久不用都生疏了,竟然一开始没想到。)
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 55;
bool vis[N] = {false};
int a[N][N] = {0},sum,n,pp,b[N];
bool fg = false;
void dfs(int rt,long long sm,int tp)
{
if(rt == n && sm == sum)
{
fg = true;
for(int i=1;i<=n;i++)
{
if(i>1) printf(" "); printf("%d",b[i]);
}
return ;
}
if(rt == n) return ;
if(sm >= sum || sum - sm < pp-tp || fg == true) return ; //减枝
for(int i=1;i<=n;i++)
{
if(vis[i] == true) continue;
vis[i] = true;
b[rt+1] = i;
dfs(rt+1,sm+a[n][rt+1]*i,tp+i);
if(fg == true) return ;
vis[i] = false;
}
}
int main(void)
{
a[1][1] = 1;
for(int i=2;i<=12;i++)
{
for(int j=1;j<=i;j++) a[i][j] = a[i-1][j-1] + a[i-1][j];
}
scanf("%d%d",&n,&sum);
//for(int i=1;i<=n;i++) printf("%d ",a[n][i]); printf("\n");
pp = 0;
for(int i=1;i<=n;i++) pp += i;
dfs(0,0,0);
return 0;
}