luogu4187 [USACO18JAN]Stamp Painting (dp)

可以发现,只要存在连续k个相同的,这个情况就一定是合法情况

然而这个不太好算,我们算不存在k个相同的,然后用$m^n$把它减掉

设f[i]为前i个,没有连续k个的

显然$f[i]=m^i ,i<K$

然后我们现在想把f[i]转移过来,只要取f[i-k+1]..f[i-1]的所有情况,然后在每个的后面都涂上与这种情况的最后一个颜色不相同的颜色就可以了。容(bu)易(hui)证明这样做是不重不漏的

所以$f[i]=(M-1)sum_{j=i-K+1}^{i-1}f[j]$

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define pa pair<int,int>
 4 using namespace std;
 5 const int maxn=1000010,mod=1e9+7;
 6 
 7 inline ll rd(){
 8     ll x=0;char c=getchar();
 9     while(c<'0'||c>'9') c=getchar();
10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
11     return x;
12 }
13 
14 ll N,M,K;
15 ll f[maxn];
16 ll ans=1,sum;
17 
18 int main(){
19     int i,j,k;
20     N=rd(),M=rd(),K=rd();
21     for(i=1;i<=N;i++){
22         ans=(ans*M)%mod;
23         if(i<K) f[i]=ans,sum=(sum+ans)%mod;
24     }
25     for(i=K;i<=N;i++){
26         f[i]=(sum*(M-1))%mod;
27         sum=(sum+f[i]-f[i-K+1])%mod;
28     }
29     printf("%d
",((ans-f[N])%mod+mod)%mod);
30 }
原文地址:https://www.cnblogs.com/Ressed/p/9661855.html