analysis
开始用了一个全排列的算法,n=12算下来会爆炸,于是就用了一个函数来求中间的数列的值来可行性剪枝,函数n^2,结果剪了枝还是没什么用
后面推了下公式,发现对于4个数a,b,c,d来说,最后的N=a+3b+3c+d,对于5个数a,b,c,d,e来说,最后的N=a+4b+6c+4d+e,这个时候隐隐约约觉得数的位置和其系数之间有关系,若可以通过位数来确定其系数的话就不用N^2求和了
殊不知这就是一个杨辉三角,自己还是太弱了啊
预处理一下杨辉三角然后剪两下枝就好了
code
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define anti_loop(i,start,end) for(register int i=start;i>=end;--i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
#define ll long long
#define db double
int n,SUM;
const int maxn=12+10;
bool vis[maxn];
int permulate[maxn];
int yhsj[maxn][maxn];
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
while(r>='0'&&r<='9'){x=(x<<3)+(x<<1)+r-'0';r=getchar();}
x*=neg;
}
inline int _SUM(register int _n){
if(_n==0)return 0;
int _sum=0;
loop(i,1,_n)_sum+=yhsj[n][i]*permulate[i];
return _sum;
}
void dfs(register int pos,register int w){
if(w>SUM)return;
if(pos>n){
if(_SUM(n)==SUM){
for(register int i=1;i<=n;++i)printf("%d ",permulate[i]);
exit(0);
}
return;
}
loop(_i,1,n){
if(vis[_i])continue;
//if(sum+i+permulate[pos-1]>SUM)continue;
permulate[pos]=_i;
if(_SUM(pos)>SUM)continue;
vis[_i]=true;
dfs(pos+1,w+_i*yhsj[n][pos]);
vis[_i]=false;
}
}
inline void pre(){
yhsj[1][1]=1;
loop(i,2,n){
loop(j,1,i){
yhsj[i][j]=yhsj[i-1][j]+yhsj[i-1][j-1];
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain2.txt","r",stdin);
#endif // ONLINE_JUDGE
read(n),read(SUM);clean(yhsj,0);
clean(vis,0);clean(permulate,0);
pre();
dfs(1,0);
return 0;
}