luogu P1118 [USACO06FEB]数字三角形`Backward Digit Su`…

在这里插入图片描述

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AndrewMe8211

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值