问题描述
  观察这个数列:
  1 3 0 2 -1 1 -2 ...

  这个数列中后一项总是比前一项增加2或者减少3。

  栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b的整数数列可能有多少种呢?
输入格式
  输入的第一行包含四个整数 n s a b,含义如前面说述。
输出格式
  输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以100000007的余数。
样例输入
4 10 2 3
样例输出
2
样例说明
  这两个数列分别是2 4 1 3和7 4 1 -2。
数据规模和约定
  对于10%的数据,1<=n<=5,0<=s<=5,1<=a,b<=5;
  对于30%的数据,1<=n<=30,0<=s<=30,1<=a,b<=30;
  对于50%的数据,1<=n<=50,0<=s<=50,1<=a,b<=50;
  对于70%的数据,1<=n<=100,0<=s<=500,1<=a, b<=50;
  对于100%的数据,1<=n<=1000,-1,000,000,000<=s<=1,000,000,000,1<=a, b<=1,000,000。
 
第一项未知,从第二项开始每一项比前一项加a或减b,最后加到一块,a和-b一共加了n*(n-1)/2次,这是固定不变的,所以只需要知道对应的a加了k次有多少种情况,然后如果可以组成这样的数列,就加到总的ans里,并不是所有的k都能组成题目要求的数列,实际上,
如果第i次,我们选择了加a,以后的每一项都要加a,即加了n - i +1个a,然后对于所有的选择加a的位置i,求和n - i + 1,就是加a的总次数,用动态规划,会计算所有的情况,最后采取判断是否能构成满足的数列,dp[i][j]记录前i项有几个加a,显然前0项,dp[0][0] = 1,
前1项,dp[1][0] = 1,其实所有的i,dp[i][0] = 1,dp[1][1] += dp[0][0] = 1,前两项dp[2][1] = dp[1][0] = 0,dp[2][2] = dp[1][0] = 1,dp[2][3] = dp[1][1] = 1.
对于所有的j(i<=j<=i*(i+1)/2),满足dp[i][j]=dp[i-1][j]+dp[i-1][j-i],其他的dp[i][j]=dp[i-1][j],由于i只跟i-1有关,再前面的不需要记录,也就是i真正需要开到2,而且题目数据也大,开数组dp[2][1000001],最后对于所有的选择情况k,判断s-k*a+(n*(n-1)/2-k)*b是否能整出n,因为首项x是要被加n次的,也就是s-k*a+(n*(n-1)/2-k)*b=nx。
代码:
#include <iostream>
using namespace std;
typedef long long ll;
const ll mod = 100000007;
ll dp[5000001];
int main() {
    ll n,s,a,b;
    cin>>n>>s>>a>>b;
    ll ans = 0;
    dp[0] = 1;
    for(ll i = 1;i < n;i ++) {
        for(ll j = i * (i + 1) / 2;j >= i;j --) {
            dp[j] = (dp[j - i] + dp[j]) % mod;
        }
    }

    for(ll i = 0; i <= (n - 1) * n / 2; i ++) {
        ll t = s - i * a + ((n - 1) * n / 2 - i) * b;
        if(t % n == 0) ans = (ans + dp[i]) % mod;
    }
    cout<<ans<<endl;
    return 0;
}