非常报数

【题目描述】
摩尔们的整队报数,比较特别。第一个摩尔报数为0,从第二摩尔开始,报数为它前面摩尔报数加1或者减1。
如此这样n个摩尔报数的情况,形成多种数列。譬如,有4个摩尔报数,所有可能的报数数列共有如下8种:
0 1 2 3
0 1 2 1
0 1 0 1
0 1 0 -1
0 -1 0 1
0 -1 0 -1
0 -1 -2 -1
0 -1 -2 -3
对于每一种数列,都有其对应的各项之和。以上8种数列中,对应的和为6、4、2、0、0、-2、-4、-6 。其中和为0的有2种。
现在想知道的是n个摩尔排成一列,按照摩尔报数规则报数,报数形成的数列之和为s的情况有多少种?
【输入格式】
共一行,两个正整数,分别为n和s。
【输出格式】
一个数x,表示n个摩尔报数,共有x种数列之和为s。
【样例输入】
4 0
【样例输出】
2
【数据范围】
n<=30
【分析】
带剪枝的搜索,如果当前的和怎么增加/减少都无法达到输入的s就退出。

#include<bits/stdc++.h>
using namespace std;
const int N=35;
int a[N];
int n,s,ans=0;
void dfs(int step,int sum){
  if (step>n){
    if (sum==s) ans++;
    return;
  }
  int k=n-step+1;
  if (sum+(2*a[step-1]+1+k)*k/2<s) return;
  if (sum+(2*a[step-1]-1-k)*k/2>s) return;
  a[step]=a[step-1]+1;dfs(step+1,sum+a[step]);
  a[step]=a[step-1]-1;dfs(step+1,sum+a[step]);
}
int main(){
  cin>>n>>s;
  a[1]=0;
  dfs(2,0);
  printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值