AGC013 D Pilling Up - dp

首先考虑一个错误做法:令dp[i][j]表示前i个操作有j个黑球的方案数,这样显然会重复计数。
改为dp[i][j][k]表示前i个操作,用过箱子里前j+k个球,其中j个是黑球,k个是白球的方案数,然后贪心转移,这样显然正确性是对的,但是复杂度原地爆炸。
考虑第一个做法,显然一个输出序列对应初始黑球数量是一段区间,而之所以不能比下界还要低是因为若如此就会途中发生没有黑球的情况,因此我们强制要求操作期间有一个时刻黑球数目变成0,再开一维记录这个即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 3010
#define mod 1000000007
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define upd(x,y) (x+=y,(x>=mod?x-=mod:0))
using namespace std;
int dp[2][N][2];
int main()
{
    int n,m,ans=0,now=0,nxt=1;
    scanf("%d%d",&n,&m);
    rep(i,0,n) dp[now][i][i==0]=1;
    for(int i=0;i<m;i++,swap(now,nxt)) rep(j,0,n)
    {
        if(j>0)
            upd(dp[nxt][j][j==1],dp[now][j][0]),
            upd(dp[nxt][j-1][j==1],dp[now][j][0]),
            upd(dp[nxt][j][1],dp[now][j][1]),
            upd(dp[nxt][j-1][1],dp[now][j][1]);
        if(j<n)
            upd(dp[nxt][j][0],dp[now][j][0]),
            upd(dp[nxt][j+1][0],dp[now][j][0]),
            upd(dp[nxt][j][1],dp[now][j][1]),
            upd(dp[nxt][j+1][1],dp[now][j][1]);
        dp[now][j][0]=dp[now][j][1]=0;
    }
    for(int i=0;i<=n;i++) upd(ans,dp[now][i][1]);
    return !printf("%d\n",ans);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值