玲珑杯 #10 A dp递推

本文介绍了一种使用动态规划解决棋子排列问题的方法。给定一排格子,每个格子放置黑白棋子之一,但不能出现连续a个黑棋或b个白棋的情况。通过定义状态转移方程,计算所有合法的排列方案数。

A. Black and White

题意:n个格子排在一行,每个格子里都有一枚白棋或一枚黑棋。限制:不能有连续a枚黑棋或连续b枚白棋,问有多少种方案。

tags:一开始还以为是组合数学,没想到又是dp。这mmp的还是签到题

考虑长度为 i 的合法序列与长度为 i−1 的合法序列有什么关系。定dp[i][black] 为有 i 枚棋子且最后一枚是黑色的合法方案数量,g[i]为有 i 枚棋子的合法方案数量。现假设前面 i-1 枚棋都是合法的,在 i 位置加一枚黑棋,唯一不合法的情况就是最后的a枚棋子全是黑色,即g[i]=g[i-1]-dp[i-a][white]。白棋同理,递推到g[n]即是答案。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define F(i,b,a)  for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 2e6+10, mod=1e9+7;

int a, b, n, T;
ll dp[N][2], g[N];
int main()
{
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d %d", &a, &b, &n);
        dp[0][0]=dp[0][1]=1, g[0]=1;
        FF(i,1,n) {
            if(i-a>=0) dp[i][0]=g[i-1]-dp[i-a][1];
            else dp[i][0]=g[i-1];
            if(i-b>=0) dp[i][1]=g[i-1]-dp[i-b][0];
            else dp[i][1]=g[i-1];
            g[i]=(dp[i][0]+dp[i][1])%mod;
        }
        printf("%lld\n", (g[n]+mod)%mod);
    }

    return 0;
}
View Code

转载于:https://www.cnblogs.com/sbfhy/p/6413468.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值