zoukankan      html  css  js  c++  java
  • BZOJ5190 Usaco2018 Jan Stamp Painting(动态规划)

      可以大胆猜想的一点是,只要有不少于一个长度为k的颜色相同子串,方案就是合法的。

      直接算有点麻烦,考虑减去不合法的方案。

      一个正(xue)常(sha)的思路是枚举序列被分成的段数,问题变为用一些1~k-1的数组成n的方案数,这显然是可以容斥的。但好像对每一种都进行容斥就不太好办了。

      暴力二维dp是很容易想到的。考虑去掉一维的暴力,设f[i]为前i位不合法染色方案数,枚举这一段的长度转移。这显然是可以前缀和的。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 1000010
    #define P 1000000007
    int n,m,k,f[N],ans;
    int ksm(int a,int k)
    {
        int s=1;
        for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
        return s;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj5190.in","r",stdin);
        freopen("bzoj5190.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),k=read();
        ans=ksm(m,n);
        for (int i=1;i<=n;i++)
        if (i-k+1>0) f[i]=(f[i-1]+1ll*(f[i-1]-f[i-k])*(m-1))%P;
        else f[i]=(f[i-1]+1ll*f[i-1]*(m-1)+m)%P;
        cout<<((ans-f[n]+f[n-1])%P+P)%P;
        return 0;
    }
  • 相关阅读:
    P1828 [USACO3.2]香甜的黄油 Sweet Butter 题解
    P2058 海港 题解
    浅谈三分算法
    海伦公式的证明
    一年一回首
    再谈单调队列优化 & 背包九讲
    浅谈单调队列
    P1440 求m区间内的最小值 题解
    CF1374B Multiply by 2, divide by 6 题解
    组合数、杨辉三角与递推算法
  • 原文地址:https://www.cnblogs.com/Gloid/p/9821731.html
Copyright © 2011-2022 走看看