AcWing 1214. 波动数列
原题链接
中等
作者:
牛奶小柒Luke
,
2021-03-13 23:33:34
,
所有人可见
,
阅读 380
x x + d1 x + d1 + d2 x + d1 + d2 + d3 .... x + d1 + .... + dn-1
nx + (n-1)d1 + (n - 2)d2 + ... + dn-1 = s
x = (s - ((n-1)d1 + (n-2)d2 + ... + dn-1)) / n
即为组合类型:(n-1)d1 + (n-2)d2 + ... + dn-1 与s mod n 的余数相同的方案数
状态表示:f[i][j]表示所有只考虑前i项,且当前的总和s/n的余数==j的方案数的集合
状态计算:无论是+a还是-b,所有种类的第i项都相同
最后一项是+a的所有方案:f[i - 1][c] c + i*a = j(mod n) -> c == j - i*a(mod n)
最后一项是-b的所有方案:f[i - 1][c] c - i*b = j(mod n) -> c == j + i*b(mod n)
第i项的系数为n - i
则+a方案:f[i - 1][j - (n - 1)*a] -b方案:f[i - 1][j + (n - 1)*b]
因为方案数为正,则取s mod n的正余数
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1010,mod = 100000007;
int n,s,a,b;
int f[N][N];
int get_mod(int a,int b){ //a模b的正余数
return (a % b + b) % b;
}
int main(){
cin >> n >> s >> a >> b;
f[0][0] = 1;
for(int i = 1;i < n;++i){
for(int j = 0;j < n;++j){
f[i][j] = (f[i - 1][get_mod(j - (n - i) * a,n)] + f[i - 1][get_mod(j + (n - i) * b,n)]) % mod;
}
}
cout << f[n - 1][get_mod(s,n)] << endl;
return 0;
}