【CodeForces - 474D】Flowers (线性dp)

探讨Marmot在特定条件下享用晚餐的算法问题,包括如何排列红白花朵以满足连续白花数量为k倍数的要求,以及通过动态规划解决类似问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题干:

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).

Examples

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).

题目大意:

把红花和白花摆成一排,并且要求若出现白花,它们连续的数量必须是k的倍数。

给我们 n,接下来的n次询问。和k   (n,k<100000)

每行 一个 a和b。

设f(k)为长度为k的满足条件的一排花 的 可能的数量

最后求f(a)+f(a+1)+...+f(b)

(不要理解成给定一个区间一共b个,去求a到b的,而是一共a个,一共a+1个....一共b个  的可能情况的和)

另一个题目大意:

话说某个幸运的小伙伴X拿到了kevin女神送的蛋糕,然而他的吃法非常奇特,他独创了两种吃蛋糕的办法:一、一次吃一整个蛋糕;二、一次吃k个蛋糕。

那么,当蛋糕数量为x1到x2之间时,一共能有几种不同的吃法呢?

由于答案很大,输出结果mod 1000000007的值

解题报告:

   直接dp就完事了,然后再维护一个前缀和。如果按照第一种题意,那就看AC代码2,第二种题意就看AC代码1。但是第一种题意可以转化成第二种,因为不管什么花其实可以看成是同一种,只不过有两种摆法就是了。

AC代码1:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
ll dp[MAX],ans[MAX];
const ll mod = 1e9 + 7;
int main()
{
	int t,k;
	cin>>t>>k;
	dp[0]=1;
	for(int i = 1; i<MAX; i++) {
		dp[i] = dp[i-1];
		if(i >= k) dp[i] += dp[i-k];
		dp[i]%=mod;
	}
	int x,y;
	for(int i = 1; i<MAX; i++) {
		ans[i] = ans[i-1] + dp[i];
	}
	while(t--) {
		scanf("%d%d",&x,&y);
		printf("%lld\n",(ans[y] - ans[x-1] + mod)%mod);
	}

	return 0 ;
 }

AC代码2:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
ll dp[MAX][2],ans[MAX];//dp[][0]代表红花,dp[][1]代表白花 
const ll mod = 1e9 + 7;
int main()
{
	int t,k;
	cin>>t>>k;
	dp[0][0]=1;
	dp[0][1]=0;
	for(int i = 1; i<MAX; i++) {
		dp[i][0] = dp[i-1][0];
		dp[i][1] = dp[i-1][1];
		if(i >= k) dp[i][1] += dp[i-k][0] + dp[i-k][1];
		dp[i][1]%=mod;dp[i][0]%=mod;
	}
	int x,y;
	for(int i = 1; i<MAX; i++) {
		ans[i] = ans[i-1] + dp[i][0] + dp[i][1];
	}
	while(t--) {
		scanf("%d%d",&x,&y);
		printf("%lld\n",(ans[y] - ans[x-1] + mod)%mod);
	}

	return 0 ;
 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值