题目描述
题目分析
数列问题,由于前一项和后一项有关联,考虑用动态规划,但由于初项未知,很难建立状态。故尝试从数学角度求解。
不妨设为数列第
项。
为数列的和。数列每一项与后一项的差值为
,则:
设,代换得:
,移项后得:
由于此处的为任意整数,因此满足
的方案数即为本题答案。
设的前
项和为
,
为满足
的方案数。
初始状态即为满足
的方案数(0或1)
状态转移方程(选择+a或-b)为:
我的代码
注意s的范围是long long。此外注意把任何被取余数转化为结果不变的正数后再取余!否则取余结果为负数,会有误。
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
using namespace std;
typedef long long ll;
ll dp[1005][1005];
ll n, s, a, b;
int main(void)
{
cin >> n >> s >> a >> b;
for (int i = 0; i < n; i++)
{
if ((s % n + n) % n == i) dp[0][i] = 1;
else dp[0][i] = 0;
}
for (int i = 1; i < n; i++)
{
for (int j = 0; j < n; j++)
{
dp[i][j] = dp[i - 1][(j - (i * a) % n + n) % n] + dp[i - 1][(j + i * b) % n];
dp[i][j] %= 100000007;
}
}
ll ans = dp[n - 1][0];
cout << ans;
return 0;
}