Educational Codeforces Round 62 (Rated for Div. 2) E. Palindrome-less Arrays dp 計數 組合數學

題目鏈接:https://codeforces.com/contest/1140/problem/E

題目大意

給定一個串,不能出現長度爲奇數(len3)(len\geq3)的迴文串,1-1的位置可以填1k1-k的所有數,問有多少種合法的方案,輸出方案數。

題解思路

思路來源於官方題解,看完就是恍然大悟的感覺。
不能出現長度爲奇數(len3)(len\geq3)的迴文串 ==沒有長度爲33的迴文串
這樣就可以分奇偶兩個串,相鄰的兩個數不相同。

通過枚舉可以發現,一個連續的1-1串對答案的貢獻只和kk以及左右兩個數是否相等有關,和左右兩個數的具體值無關

我用 dp[len][0/1]dp[len][0/1]表示長度爲lenlen1-1串對答案的貢獻,00表示串左右兩個數相同 11表示左右兩個數不同

比較懶,應該寫個函數的,直接複製了一遍
在這裏插入圖片描述
這是我做的時候隨便寫的樣例,可以發現:
dp[i][1]dp[i][1]的組成來源於上一長度中在[1,k][1,k]中不爲當前數的狀態和
就是dp[i1][0](k1)dp[i-1][0]*(k-1)
dp[i][0]dp[i][0]的組成來源於上一長度中在[1k][1-k]中不爲當前數的狀態和
就是dp[i1][1]+dp[i1][0](k2)dp[i-1][1]+dp[i-1][0]*(k-2)

另外還要單獨考慮:
1.全爲1-1的情況,第一個位置有kk種選擇,後面的都有k1k-1種選擇,對答案的貢獻就是k(k1)len1k*(k-1)^{len-1}
2.只有一邊有約束的情況,臨近約束的點有k1k-1種選擇,後面每個數都有k1k-1種選擇,對答案的貢獻是(k1)len(k-1)^{len}

每一部分的貢獻都是乘在ansans上的(相互獨立)

#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define int ll
#define debug cout<<"fuck"<<endl;
#define pb  push_back
const int mod=(int)998244353;
const int maxn=(int)2e5+5;
int m[maxn];
int dp[maxn][2];
vector<int>a,b;
ll quick_pow_mod(ll a,ll b,ll c)
{
    ll res=1;
    while(b)
    {
        if(b & 1)
        {
            res=(res*a)%c;
        }
        a=(a*a)%c;
        b=b>>1;
    }
    return res;
}
int n,k;
void init()
{
    //0表示不同,1表示相同
    dp[1][1]=k-1;
    dp[1][0]=k-2;
    for(int i=2;i<maxn;i++)
    {
        dp[i][1]=(dp[i-1][0]*(k-1))%mod;
        dp[i][0]=(dp[i-1][1]+dp[i-1][0]*(k-2))%mod;
    }
}
signed main()
{
    IOS
    bool fail=0;
    cin>>n>>k;
    init();
    /*for(int i=1;i<=5;i++)
    {
        cout<<dp[i][0]<<' '<<dp[i][1]<<endl;
    }*/
    for(int i=1;i<=n;i++)
    {
        cin>>m[i];
        if(i%2)a.pb(m[i]);
        else b.pb(m[i]);
        if(m[i]!=-1&&i>=3&&m[i]==m[i-2])
        {
            fail=1;
        }
    }
    if(fail==1)
    {
        cout<<0<<endl;
        return 0;
    }
    int flag;
    ll ans=1;
    for(int i=0;i<a.size();i++)
    {
        int len=0;
        if(a[i]==-1&&i==0)
        {
            len=1;
            while(a[i+1]==-1&&i+1<a.size())
            {
                i++;
                len++;
            }
            if(len==a.size())
            {
                ans*=k*quick_pow_mod(k-1,len-1,mod);
                ans%=mod;
                break;
            }
            else
            {
                ans*=quick_pow_mod(k-1,len,mod);
                ans%=mod;
                continue;
            }
        }
        else if(a[i]==-1&&i>=1)
        {
            int pre=a[i-1];
            len=1;
            while(a[i+1]==-1&&i+1<a.size())
            {
                i++;
                len++;
            }
            if(i==a.size()-1)
            {
                ans*=quick_pow_mod(k-1,len,mod);
                ans%=mod;
            }
            else
            {
                if(a[i+1]==pre)
                {
                    ans*=dp[len][1];
                    ans%=mod;
                }
                else
                {
                    ans*=dp[len][0];
                    ans%=mod;
                }
            }
        }
    }
    for(int i=0;i<b.size();i++)
    {
        int len=0;
        if(b[i]==-1&&i==0)
        {
            len=1;
            while(b[i+1]==-1&&i+1<b.size())
            {
                i++;
                len++;
            }
            if(len==b.size())
            {
                ans*=k*quick_pow_mod(k-1,len-1,mod);
                ans%=mod;
                break;
            }
            else
            {
                ans*=quick_pow_mod(k-1,len,mod);
                ans%=mod;
                continue;
            }
        }
        else if(b[i]==-1&&i>=1)
        {
            int pre=b[i-1];
            len=1;
            while(b[i+1]==-1&&i+1<b.size())
            {
                i++;
                len++;
            }
            if(i==b.size()-1)
            {
                ans*=quick_pow_mod(k-1,len,mod);
                ans%=mod;
            }
            else
            {
                if(b[i+1]==pre)
                {
                    ans*=dp[len][1];
                    ans%=mod;
                }
                else
                {
                    ans*=dp[len][0];
                    ans%=mod;
                }
            }
        }
    }

    cout<<ans<<endl;


    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章