蓝桥杯 波动数列

33 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第34天,点击查看活动详情

[蓝桥杯 2014 省 A] 波动数列

题目描述

观察这个数列:

1,3,0,2,1,1,2,1,3,0,2,-1,1,-2, \cdots

这个数列中后一项总是比前一项增加 22 或者减少 33

栋栋对这种数列很好奇,他想知道长度为 nn 和为 ss 而且后一项总是比前一项增加 aa 或者减少 bb 的整数数列可能有多少种呢?

输入格式

输入的第一行包含四个整数 n,s,a,bn,s,a,b,含义如前面说述。

输出格式

输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以 100000007100000007 的余数。

样例 #1

样例输入 #1

4 10 2 3

样例输出 #1

2

提示

【样例说明】

这两个数列分别是 2 4 1 3 和 7 4 1 -2。

【数据规模与约定】

对于 10%10\% 的数据,1n51 \le n \le 50s50 \le s \le 51a,b51 \le a,b \le 5

对于 30%30\% 的数据,1n301 \le n \le 300s300 \le s \le 301a,b301 \le a,b \le 30

对于 50%50\% 的数据,1n501 \le n \le 500s500 \le s \le 501a,b501 \le a,b \le 50

对于 70%70\% 的数据,1n1001 \le n \le 1000s5000 \le s \le 5001a,b501 \le a,b \le 50

对于 100%100\% 的数据,1n10001 \le n \le 1000109s109-10^9 \le s \le 10^91a,b1061 \le a,b \le 10^6

时限 1 秒, 256M。蓝桥杯 2014 年第五届省赛

分析

这也是一个dp题,可以通过化简得到一个式子,最后分成两种情况讨论。

代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define int long long
#include <map>
using namespace std;
const int N=1010;
const int mod=100000007;
int n,s,a,b;
int get_mod(int a,int b){
	return (a%b+b)%b;
}
int dp[N][N];
signed main(){
	cin>>n>>s>>a>>b;
	dp[0][0]=1;
	for(int i=1;i<n;i++){
		for(int j=0;j<n;j++){
			dp[i][j]=(dp[i-1][get_mod(j-(n-i)*a,n)]+dp[i-1][get_mod(j+(n-i)*b,n)])%mod;
		}
	}
	cout<<dp[n-1][get_mod(s,n)];
	return 0;
}