【AT2370】Piling Up

题目

有红蓝球各无限多个,初始时任意从中选择 n 个放入盒子。
初始有一个空的序列,接下来依次做 m 组操作,每组操作为依次执行下述三个步骤:
(1)从盒子中取出任意一个球插入序列尾;
(2)往盒子中放入红蓝各一个球;
(3)从盒子中取出任意一个球插入序列尾;
m 次操作后,有多少种可能的不同颜色序列,答案对 10 9 + 7 取模。

解法:动态规划

f i , j 表示 i 次操作后盒中剩余 j 个红球,则剩余 n j 个蓝球。按照当前取出的两个球的颜色分类讨论,有四种转移方式:

{ f i , j f i , j 1 ( j > 0 ) f i , j f i , j ( j > 0 ) f i , j f i , j ( j < n ) f i , j f i , j + 1 ( j < n )

然后这样算显然会有重复,至于去重嘛。。听大佬说只要做两遍dp, A n s = d p ( n , m ) d p ( n 1 , m ) 。(证明之类的,挖个坑再说23333)

代码

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const long long p=1000000007ll;
long long f[3001][3001];
int n,m;

long long dp(int n,int m){
    memset(f,0,sizeof(f));
    for(int i=0;i<=n;++i)f[0][i]=1ll;
    for(int i=1;i<=m;++i)for(int j=0;j<=n;++j){if(j)(f[i][j]+=f[i-1][j]+f[i-1][j-1])%=p;if(j<n)(f[i][j]+=f[i-1][j]+f[i-1][j+1])%=p;}
    long long res=0ll;for(int i=0;i<=n;++i)(res+=f[m][i])%=p;return res;
}

int main(){
    scanf("%d%d",&n,&m);
    printf("%lld",(dp(n,m)-dp(n-1,m)+p)%p);
}

猜你喜欢

转载自blog.csdn.net/ezoixx174/article/details/81636921