zoj 3747 Attack on Titans 递推 计数dp

本文介绍了一种使用动态规划解决特定排列组合问题的方法,该问题要求构造由三种士兵(G、R、P)组成的序列,其中G士兵需满足至少m个连续出现,R士兵则需满足至多k个连续出现,而P士兵没有限制。文章提供了完整的C++代码实现,并通过取模操作确保结果在一定范围内。

题意:给定三种士兵G,R,P,有无限个,要求取出一个排列为n人,要求满足至少m个连续个G士兵,至多k个连续的R士兵,P士兵不作要求。求排列总数,对1000000007取模。
思路:http://blog.youkuaiyun.com/cc_again/article/details/10858813。不是很懂取模什么意思

#include<cstdio>
#include<cstdlib>
#include<time.h>
#define ll long long
const int maxn = 1000000+10;//至少m个G   至多k个R   p任意 
const int mod=1000000007;
ll dp[maxn][3];//[0]表示第i个为G,[1]表示R  [2] 表示p 
int n,m,k;
int solve(int u,int r)//代表G至多u个,   R至多r个 
{
	for(int i=1;i<=n;i++)
	{
		ll sum= (dp[i-1][0]+dp[i-1][1]+dp[i-1][2])%mod;//中间结果用ll存,否则溢出 
		dp[i][2]=sum;
		if(i<=u)
		dp[i][0]=sum;
		else if(i==u+1)
		dp[i][0]=(sum-1)%mod;
		else if(i>u+1)
		dp[i][0]=(sum-dp[i-u-1][1]-dp[i-u-1][2])%mod;
		
		if(i<=r)
		dp[i][1]=sum;
		else if(i==r+1)
		dp[i][1]=(sum-1)%mod;
		else if(i>r+1)
		dp[i][1]=(sum-dp[i-r-1][0]-dp[i-r-1][2])%mod;
	}
	return (dp[n][0]+dp[n][1]+dp[n][2])%mod;
}
int main()
{
	//freopen("in.txt","r",stdin);
	while(scanf("%d%d%d",&n,&m,&k)!=EOF)
	{
		dp[0][0]=1;dp[0][1]=dp[0][2]=0;
		int ans=((solve(n,k)-solve(m-1,k))%mod+mod)%mod;
		printf("%d\n",ans);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值