2026年牛客多校第三场个人题解

因为比较忙,我只做了F和两个签到题。

F

这个数据范围很容易让我们想到状压。

对于每列的状态数是 \(3^n\) 种,但是其实能够发现,真正合法的状态数不会太多。

爆搜出所有有效状态,发现在 \(n=9\) 的情况下是 \(782\) 种。

仔细想一想这个数字是怎么来的。

对于前两个位置,我们的选法是有以下六种:\(01,02,10,12,20,21\)

对于后续的任意一个位置,只有两种选择:

  • 等于\(s_{i-2}\)的位置
  • 等于\(3\oplus s_{i-1}\oplus s_{i-2}\) (写的比较抽象,实际上也就是那个没有出现的颜色)

即,任意一个位置都有两种选择。

故,方案数是\(6\times 2^{n-2}\)

我们将上述的两种选择分别记成 \(0,1\),可以压缩成一个二进制的状态,且前两个位置固定成\(01\),最后可以让整个方案数乘\(6\)

\(dp_{k,sta}\)表示当前已经递推到了第\(k\)个位置,当前的二进制状态为 \(sta\) 的方案数。

可以考虑递推:

\(dp_{k,i}= \sum dp_{k-1,j} \times A_{j,i}\)

其中,预处理出\(A_{i,j}\)表示对于某个二进制状态\(i\)转移到二进制状态\(j\)的方案数。

对于任意 \(k-1\) 到$ k $ 的递推式的转移是相同的,于是你可以使用矩阵快速幂优化该转移。

\(dp_k=A^{k-1}\)

这道题,我们钦定了前两个位置为\(01\),最终的方案数乘\(6\)

\(D=2^{n-2}\)时间复杂度为\(O(D^3\log m)\)

似乎有一些\(n=1,m=1\)时的特判需要写。

#include<bits/stdc++.h>
#define fi first 
#define se second
#define pb push_back

using ll=long long;
using namespace std;
typedef pair<int,int>pii;
const int N=800;
const int mod=998244353;
struct Matrix {
    int h,l;
    vector<vector<int>>v;
    Matrix():v(N,vector<int>(N,0)){}
    Matrix(int H,int L,bool one=0):h(H),l(L),v(H+2,vector<int>(L+2,0)){
        if(one) for(int i=0;i<h;++i) v[i][i]=1;
        return;
    }
    Matrix(int H,int L,vector<vector<int>>vv):h(H),l(L),v(vv){
    }
};
Matrix operator *(const Matrix &x,const Matrix &y) {
    Matrix ans(x.h,y.l);
    for(int i=0;i<x.h;++i) for(int k=0;k<x.l;++k){
        if(x.v[i][k]==0)continue;
        for(int j=0;j<y.l;++j)ans.v[i][j]=(ans.v[i][j]+1ll*x.v[i][k]*y.v[k][j])%mod;
    } 
    return ans;
}
Matrix ksm(Matrix x,int p) {
    Matrix ans(x.h,x.l,1);
    while(p) {
        if(p&1) ans=ans*x;
        p>>=1,x=x*x;
    }
    return ans;
}
ll qpow(ll x,int y){
    ll res=1;
    while(y){
        if(y&1)res=res*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return res;
}
void Silverwolf(){
    int n,m;
    cin>>n>>m;
    vector<int>col(n+1,0);
    int cnt=0;
    int res=0;
    vector<string>vt;
    auto dfs=[&](auto &&dfs,int pos,string now)->void{
        if(pos==n+1){
            vt.push_back(now);
            return;
        }
        if(pos==1){
            for(int i=0;i<=2;i++){
                col[pos]=i;
                char ch='0'+i;
                // cout<<ch;
                dfs(dfs,pos+1,now+ch);
            }
        }else{
            for(int i=0;i<=2;i++){
                if(col[pos-1]!=i){
                    col[pos]=i;
                    char ch=i+'0';
                    dfs(dfs,pos+1,now+ch);
                }
            }
        }
    };
    dfs(dfs,1,"");
    if(m==1){
        cout<<vt.size()<<'\n';
        return;
    }
    if(n==1){
        //01
        //02
        //10
        //12
        //20
        //21 后面每一位都有两种选择
        ll ans=qpow(2,m-2);
        ans=ans*6%mod;
        cout<<ans<<'\n';
        return;
        
    }
    
    int sz=vt.size();
    vector<vector<int>>ma(sz/6,vector<int>(sz/6,0));
    for(int i=0;i<sz/6;i++){
        for(int j=0;j<sz;j++){
            auto chk=[&](string a,string b)->bool{
                for(int k=0;k<a.length();k++){
                    if(a[k]==b[k])return false;
                }
                return true;
            };
            auto get_2=[&](string b)->int{
                int num=0;
                for(int k=2;k<b.length();k++){
                    int now=b[k]-'0';
                    int lst=b[k-1]-'0';
                    int lst2=b[k-2]-'0';
                    if(now!=lst&&now!=lst2)num=num*2+1;
                    else num=num*2;
                }
                return num;
            };
            if(chk(vt[i],vt[j])){
                ma[get_2(vt[i])][get_2(vt[j])]++;
            }
        }
    }

    Matrix matrix(sz/6,sz/6,ma);
    //你发现状态数最多768种
    Matrix a=ksm(matrix,m-1);

    ll ans=0;
    for(int i=0;i<sz/6;i++){
        for(int j=0;j<sz/6;j++){
            ans=(ans+a.v[i][j])%mod;
        }
    }
    ans=ans*6%mod;
    cout<<ans<<'\n';
    
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    // init();
    // int T;cin>>T;while(T--)
    Silverwolf();
    return 0;
}

还做了下L和K。

导航