USACO 2018 January Contest, Gold Problem 3. Stamp Painting ——DP

This way

题意:

现在有一个长度为n的布,你有m个颜色不同的大小为k的章,你需要在这张布上盖章,可以部分区间覆盖,但是不能超过这个布的大小,问你最终这张布的颜色的情况数。

题解:

我想了两个小时还是没想出来呀,但是已经非常接近答案了,就有一块地方想错了。
那么这块布每一个单位有m种可能的颜色,但是由于章的大小为k,所以没有一块连续相同颜色的区间长度>=k的情况是不存在的,也就是说至少有一个区间的连续相同颜色长度>=k。那么我们用ans来记录已经符合的情况数,用dp记录还未符合的情况数,
我们枚举每个单位来做这道题,那么在i=k的时候,ans=m,dp[i]=dp[i-1]*m-m,也就是在k位置的时候已经有m种情况是符合要求的了,那么对于之后的情况,
a n s = ( a n s ∗ m + d p [ i − k ] ∗ ( m − 1 ) ) % m o d ans=(ans*m+dp[i-k]*(m-1))\%mod ans=(ansm+dp[ik](m1))%mod
为什么不能数dp[i-k+1]呢?
因为dp虽然不允许连续长度为k的情况存在,但是允许更小的情况存在,也就是说当dp[i-k+1]的左边有连续相同的格子>=2的时候,我们就多加了情况数。
dp的状态转移方程:
d p [ i ] = ( d p [ i − 1 ] ∗ m % m o d − d p [ i − k ] ∗ ( m − 1 ) % m o d + m o d ) % m o d dp[i]=(dp[i-1]*m\%mod-dp[i-k]*(m-1)\%mod+mod)\%mod dp[i]=(dp[i1]m%moddp[ik](m1)%mod+mod)%mod

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
const int N=1e6+5;
ll dp[N];
int main()
{
    ll n,m,k;
    scanf("%lld%lld%lld",&n,&m,&k);
    ll ans=0;
    dp[0]=1;
    for(int i=1;i<k;i++)
        dp[i]=dp[i-1]*m%mod;
    dp[k]=(dp[k-1]*m-m)%mod;
    ans=m;
    for(int i=k+1;i<=n;i++)
        ans=(ans*m+dp[i-k]*(m-1))%mod,dp[i]=(dp[i-1]*m%mod-dp[i-k]*(m-1)%mod+mod)%mod;
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值