1700*D. Flowers(DP&&前缀和&&预处理打表)

Problem - 474D - Codeforces

1700*D. Flowers(DP&&前缀和&&预处理打表)_第1张图片

题意:

        有白花和红花两种,把 x 朵花排成一排,要求白花必须连续 k 个一块放置,则有 cnt 种情况。给出 a 和 b,计算a到b之间的 x 对应的 cnt 总和,并且对1e9+7取模。

解析:

        考虑DP。

        当数量 x 小于 k 的时候,只能全部放置红花,只有一种情况。

        当数量 x 等于 k 的时候,则为两种情况,多了一种 x 朵花都为白花的情况(要求必须 k 朵连续放置)

        当数量 x 大于 k 的时候,如果最新的一朵花我们放置红色,则其情况数量等于前一朵的情况数量。如果如果最新的一朵花我们放置白色,则连续 k 朵都为白色,则情况数量等于 x-k 的情况。

所以状态转移方程为 dp[ i ] = dp[ i-1 ]+dp[ i-k ],i>k

        综上所述,状态转移方程为

                                      dp[ i ] = 1,i>=1 && i

                                      dp[ i ] = 2,i==k

                                      dp[ i ] = dp[ i-1 ]+dp[ i-k ],i>k

        并且每次询问数据范围都为1e5,所以预处理前缀和。

        注意,因为每次都取模mod,可能导致最后答案小于 0 的情况,所以此时需要加一个mod。

#include
using namespace std;
#define int long long
const int N=1e5+5,mod=1e9+7;
int t,k,dp[N],sum[N];
signed main(){
	scanf("%lld%lld",&t,&k);
	dp[1]=1;
	for(int i=1;i<=k;i++){
		dp[i]=1;
		sum[i]=sum[i-1]+1;
	}
	dp[k]+=1;
	sum[k]+=1;
	for(int i=k+1;i<=1e5;i++){
		dp[i]=(dp[i-1]+dp[i-k])%mod;
		sum[i]=(sum[i-1]+dp[i])%mod;
	}
	while(t--){
		int a,b;
		scanf("%lld%lld",&a,&b);
		printf("%lld\n",(sum[b]-sum[a-1]+mod)%mod);
	}
	return 0;
}

你可能感兴趣的:(codeforces,算法,c++,数据结构,c语言,开发语言,动态规划)