ATB279G At Most 2 Colors 学习笔记

ATB279G At Most 2 Colors 学习笔记

Luogu Link

前言

参考文献:这位巨佬的题解

题意简述

现在有一行 \(N\) 个格子和 \(C\) 种颜色。每一个格子都需涂 \(C\) 种颜色中的一种,并且任意相邻的 \(K\) 个格子最多有两种不同的颜色。

问有多少种染色方案。答案对 \(998244353\) 取模。

\(2\le K\le N\le 10^6,1\le C\le 10^9\)

做法解析

看到一行上相邻格子这种玩意不难往连续段DP方向想。设 \(f_{i,j}\) 表示前 \(i\) 个格子中,\([j,i]\) 颜色相同,\(A_{j-1},A_j\) 相异的合法方案数。

那么转移方程呢?有:

\[f_{i,j}=f_{i-1,j}[j<i] \]

\[f_{i,i}=\big(\sum_{j=i-k+2}^{i-1} f_{i-1,j}\big)+\big(\sum_{j=1}^{i-k+1}f_{i-1,j}\times (c-1)\big) \]

怎么理解这两个式子呢?作为连续段dp,我们肯定要按照新开一段与否讨论。

如果不新开一个颜色段,也就是 \(A_i=A_{i-1}\) 时,\(f_{i,j}\) 就直接继承了 \(f_{i,j-1}\)——我往这长为 \(K\) 的窗口里多塞一个和原来段尾相同的颜色,合法性一定有保证。

如果新开一个颜色段,我们又要分两种情况讨论:

  • 如果之前的那个颜色段足够长,也就是有 \(i-j'+1\ge K\),即 \(j'\le i-K+1\) 时,新的窗口中只会有那一大段 \(A_{i-1}\) 色和一个 \(A_i\) 色。那么 \(A_i\) 的颜色就有 \(c-1\) 种选择。对应的就是上文 \(\sum_{j=1}^{i-k+1}f_{i-1,j}\times (c-1)\)
  • 如果之前的那个颜色段不够长,也就是说 \(j'>i-K+1\),那么当前的窗口最左端就还有异于 \(A_{i-1}\) 的一种颜色,\(A_i\) 只能涂上这种颜色。对应的就是上文 \(\sum_{j=i-k+2}^{i-1} f_{i-1,j}\)

好了我们已经会 \(N^2\) 做法了。我们又发现 \(f\) 的第一维完全可以通过前缀和去掉。然后就 \(O(N)\) 了!

代码实现

这个前缀和似乎和平时见到的不太一样……?

这里的下标到底是原来的 \(i\) 还是 \(j\)

实际上,你再仔细看看上面那个式子,你就会发现所有 \(j\neq i\) 的状态都可以等于那个 \(j=i\) 的状态,所以我们只用记录所有 \(f_{i,i}\) 就够了,也就是说只有一维下标是有用的,所以这里只记录一维。

#include <bits/stdc++.h>
using namespace std;
namespace obasic{
    typedef long long lolo;
    template <typename _T>
    void readi(_T &x){
        _T k=1;x=0;char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')k=-1;
        for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-'0';
        x*=k;return;
    }
    template <typename _T>
    void writi(_T x){
        if(x<0)putchar('-'),x=-x;
        if(x>9)writi(x/10);
        putchar(x%10+'0');
    }
};
using namespace obasic;
const int MaxN=1e6+5,Mod=998244353;
lolo N,K,C,f[MaxN],g[MaxN];
int main(){
    readi(N),readi(K),readi(C);
    f[1]=g[1]=C;
    for(int i=2;i<=N;i++){
        lolo x=max(i-K+1,1ll);
        f[i]=(g[i-1]-g[x]+g[x]*(C-1)%Mod+Mod)%Mod;
        g[i]=(g[i-1]+f[i])%Mod;
    }
    writi(g[N]);
    return 0;
}

反思总结

善于观察式子,可能只有一维下标有用。
见到一个序列填东西,连续多少有限制,考虑连续段dp。

posted @ 2025-02-21 14:01  矞龙OrinLoong  阅读(13)  评论(0)    收藏  举报