[蓝桥杯 2014 省 A] 波动数列
题目描述
观察这个数列:
1 , 3 , 0 , 2 , − 1 , 1 , − 2 , ⋯ 1,3,0,2,-1,1,-2, \cdots 1,3,0,2,−1,1,−2,⋯ 。
这个数列中后一项总是比前一项增加 2 2 2 或者减少 3 3 3。
栋栋对这种数列很好奇,他想知道长度为 n n n 和为 s s s 而且后一项总是比前一项增加 a a a 或者减少 b b b 的整数数列可能有多少种呢?
输入格式
输入的第一行包含四个整数 n , s , a , b n,s,a,b n,s,a,b,含义如前面说述。
输出格式
输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以 100000007 100000007 100000007 的余数。
样例 #1
样例输入 #1
4 10 2 3
样例输出 #1
2
提示
【样例说明】
这两个数列分别是 2 4 1 3 和 7 4 1 -2。
【数据规模与约定】
对于 10 % 10\% 10% 的数据, 1 ≤ n ≤ 5 1 \le n \le 5 1≤n≤5, 0 ≤ s ≤ 5 0 \le s \le 5 0≤s≤5, 1 ≤ a , b ≤ 5 1 \le a,b \le 5 1≤a,b≤5;
对于 30 % 30\% 30% 的数据, 1 ≤ n ≤ 30 1 \le n \le 30 1≤n≤30, 0 ≤ s ≤ 30 0 \le s \le 30 0≤s≤30, 1 ≤ a , b ≤ 30 1 \le a,b \le 30 1≤a,b≤30;
对于 50 % 50\% 50% 的数据, 1 ≤ n ≤ 50 1 \le n \le 50 1≤n≤50, 0 ≤ s ≤ 50 0 \le s \le 50 0≤s≤50, 1 ≤ a , b ≤ 50 1 \le a,b \le 50 1≤a,b≤50;
对于 70 % 70\% 70% 的数据, 1 ≤ n ≤ 100 1 \le n \le 100 1≤n≤100, 0 ≤ s ≤ 500 0 \le s \le 500 0≤s≤500, 1 ≤ a , b ≤ 50 1 \le a,b \le 50 1≤a,b≤50;
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1000 1 \le n \le 1000 1≤n≤1000, − 1 0 9 ≤ s ≤ 1 0 9 -10^9 \le s \le 10^9 −109≤s≤109, 1 ≤ a , b ≤ 1 0 6 1 \le a,b \le 10^6 1≤a,b≤106。
时限 1 秒, 256M。蓝桥杯 2014 年第五届省赛
Java代码
import java.util.*;
class Main
{
public final static int MOD=100000007;
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
int s=sc.nextInt();
int a=sc.nextInt();
int b=sc.nextInt();
int[][] dp = new int[n+1][n]; //第i次选择a或b,且当前总和除以n的余数是j的方案数
dp[0][0] = 1;
for(int i=1;i<=n-1;i++) //第一次不需要考虑选择a或b,所以此处为n-1
{
for(int j=0;j<n;j++)
{
dp[i][j]=(dp[i-1][getMod(j-i*a,n)]+dp[i-1][getMod(j+i*b,n)])%MOD;
}
}
System.out.println(dp[n-1][getMod(s,n)]);
}
public static int getMod(int a,int b) //求a除以b的正余数
{
return (a%b+b)%b;
}
}
题目简单分析
d p [ i ] [ j ] dp[i][j] dp[i][j] 为上一个选 a a a 的方案数加上选 b b b 的方案数,此题关键公式如下
x
=
s
−
[
(
n
−
1
)
d
1
+
(
n
−
2
)
d
2
+
⋯
+
d
n
−
1
]
n
x={s-[(n-1)d_1+(n-2)d_2+\cdots+d_{n-1}]\over n}
x=ns−[(n−1)d1+(n−2)d2+⋯+dn−1]
其中, x x x 为第一个选的数,一定为整数且可以由某选择方案求得, s s s 为原序列和, d d d 为 + a +a +a 或 − b -b −b,要求原序列方案数即求 d 1 d_1 d1 到 d n − 1 d_{n-1} dn−1 的选择方案数。不难看出, s s s 与 ( n − 1 ) d 1 + ( n − 2 ) d 2 + ⋯ + d n − 1 (n-1)d_1+(n-2)d_2+\cdots+d_{n-1} (n−1)d1+(n−2)d2+⋯+dn−1 模 n n n 同余,由此可得 d p dp dp 第二个状态为对 n n n 取模的余数是 j j j 。本题解代码中,可以将 19 19 19 行中 i ∗ a i*a i∗a 等价换成 ( n − i ) ∗ a (n-i)*a (n−i)∗a 更好理解,表示 ( n − 1 ) d 1 + ( n − 2 ) d 2 + ⋯ + d n − 1 (n-1)d_1+(n-2)d_2+\cdots+d_{n-1} (n−1)d1+(n−2)d2+⋯+dn−1 中的某项。