话说好久没写算法代码了,工作了有点忙的了,不过算法始终是我的挚爱,故此还是尽量抽时间和挚爱来个约会。
Codeforces的题目是最适合练手的了,下面是一道不算难的动态规划法题目,先上题:
D. Flowers
time limit per test1.5 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
We saw the little game Marmot made for Mole’s lunch. Now it’s Marmot’s dinner time and, as we all know, Marmot eats flowers. At every dinner he eats some red and white flowers. Therefore a dinner can be represented as a sequence of several flowers, some of them white and some of them red.
But, for a dinner to be tasty, there is a rule: Marmot wants to eat white flowers only in groups of size k.
Now Marmot wonders in how many ways he can eat between a and b flowers. As the number of ways could be very large, print it modulo 1000000007 (109 + 7).
Input
Input contains several test cases.
The first line contains two integers t and k (1 ≤ t, k ≤ 105), where t represents the number of test cases.
The next t lines contain two integers ai and bi (1 ≤ ai ≤ bi ≤ 105), describing the i-th test.
Output
Print t lines to the standard output. The i-th line should contain the number of ways in which Marmot can eat between ai and bi flowers at dinner modulo 1000000007 (109 + 7).
Sample test(s)
input
3 2
1 3
2 3
4 4
output
6
5
5
Note
For K = 2 and length 1 Marmot can eat (R).
For K = 2 and length 2 Marmot can eat (RR) and (WW).
For K = 2 and length 3 Marmot can eat (RRR), (RWW) and (WWR).
For K = 2 and length 4 Marmot can eat, for example, (WWWW) or (RWWR), but for example he can’t eat (WWWR).
算法思路:
1 逐步增加计算的,那么就是逐步填表;
2 设tbl[]为动态规划的表格, 那么每新增第i个表格的时候,新格子只能填写R或者W,填写R的时候就相当于是有tbl[i-1]种填法,因为最后一个格子定了,只能填写R,如果填写W的时候呢?那就是有tbl[i-k]中写法了,因为根据题意,填写了W之后,i个格子之前的所有k个格子都只能填写W,因为W要么不出现,要么就只能k个W连着出现;
故此最终得到的状态转换公式:
tbl[i] = tbl[i-1] + tbl[i-k];
3 但是本题目稍微进了一步,因为需要求区间的和值,哇,一看好像要使用线段树的节奏,其实不需要使用线段树,只需要使用个小算法就可以,高手嘛,小算法自然顺手粘来,只要增加一个sum[]数组,然后计算sum[i] = tbl[0 – i]的和就可以使用sum[i] - sum[j-1]计算[j, i]之间的和值啦,当然计算sum[i] = tbl[0 – i]也是有点技巧的,看代码就知道了;
4 最后还增加点难度,就是会溢出,不过题目要求了求1e9 +7的Mod值
上代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
const int MOD = (int)1e9 + 7;
const int MAX_M = (int)1e5 + 1;
int t, k;
scanf("%d %d", &t, &k);
int tbl[MAX_M] = {};
for (int i = 0; i < k; i++)
{
tbl[i] = 1;
}
for (int i = k; i < MAX_M; i++)
{
tbl[i] = tbl[i - 1] + tbl[i - k];
tbl[i] %= MOD;
}
int sum[MAX_M] = {};
sum[0] = 0;
for (int i = 1; i < MAX_M; i++)
{
sum[i] = sum[i - 1] + tbl[i];
sum[i] %= MOD;
}
int a, b;
for (int i = 0; i < t; i++)
{
scanf("%d %d", &a, &b);
printf("%d\n", (sum[b] - sum[a - 1] + MOD) % MOD);
}
return 0;
}