我们设数列第一项为 $x$ ,第二项为 $x+d_1$ ,第 $i$ 项为 $x+d_1+d_2+\cdots +d_{i-1}$ ,那么对于长度为 $n$ 的序列和为 $s=x+(x+d_1)+(x+d_1+d_2)+\cdots +(x+d_1+d_2+\cdots +d_{i-1})$ ,即:
$$ s=nx+(n-1)d_1+(n-2)d_2+\cdots +(n-i)d_i+\cdots +d_{n-1},\ \ d_i \in \{a,-b\} $$
此时问题转变成:对于给定的每个 $s$ 与 $n$ ,在 $d_i$ 任意取值的情况下,等式成立的个数
由于 $x\in Z$ ,并且当 $d_i$ 全部唯一确定时, $x$ 也会唯一确定。此时我们需要确定的是,当 $d_i$ 取哪些值时 $x$ 是合法的(处于整数范围内),因此有如下等式:
$$ x=\frac{s-\[(n-1)d_1+(n-2)d_2+\cdots +(n-i)d_i+\cdots +d_{n-1}\]}{n} $$
如果 $x$ 要落在整数范围内,那么 $s$ 与 $(x-1)d_1+(n-2)d_2+\cdots +(n-i)d_i+\cdots +d_{n-1}$ 必须模 $n$ 同余
此时问题转换成:对于序列 $(n-1)d_1+(n-2)d_2+\cdots +(n-i)d_i+\cdots +d_{n-1}$ 与 $s$ 模 $n$ 同余的个数
考虑动态规划,$f[i][j]$ 表示对第 $i$ 个数选择,模 $n$ 余 $j$ 的方案数
第 $i$ 个数对应 $d_i$ ,系数为 $(n-i)$ ,因此:
-
若第 $i$ 个数为 $a$ ,即 $d_i=a$ ,有 $(n-1)d_1+(n-2)d_2+\cdots +(n-i)a$ ,即 $f[i-1][\mod((j-(n-i)*a), \ n)]$
-
同理,若第 $i$ 个数为 $-b$ ,有 $f[i-1][\mod((j+(n-i)*b),\ n)]$
最终结果为 $f[n-1][\mod(s,\ n)]$
完整代码如下:
#include <iostream>
using namespace std;
const int N = 1e3 + 10, mod = 1e8 + 7;
int get_mod(int a, int n)
{
return (a % n + n) % n;
}
int f[N][N];
int n, s, a, b;
int main()
{
cin >> n >> s >> a >> b;
f[0][0] = 1;
for(int i = 1; i <= n - 1; i++)
{
for(int j = 0; j < n; j++)
{
f[i][j] = get_mod(f[i][j] + f[i - 1][get_mod(j - (n - i) * a, n)], mod);
f[i][j] = get_mod(f[i][j] + f[i - 1][get_mod(j + (n - i) * b, n)], mod);
}
}
cout << f[n - 1][get_mod(s, n)] << endl;
return 0;
}