Educational Codeforces Round 62 (Rated for Div. 2) E

题意

如果一个数组中有 > 1 >1 的奇数回文串就是 b a d bad .
数组中 1 -1 的部分要求被替换成 1 k 1-k 的数字,最后得到的不 b a d bad 的数组有多少种

题解

如果能保证最小的奇数回文串不存在,就不会存在更大,最小的是 3 3
保证 a [ i ] ! = a [ i 2 ] a[i]!=a[i-2]
我们可以发现分奇偶讨论。

每一部分都是 1 1 1 1 X 1 1 1 1 Y 1 1 -1 -1 -1 -1\quad X\quad -1 -1 -1 -1 \quad Y\quad -1-1

对于一个 a 1 1 1 1 b a\quad -1 -1 -1 -1 \quad b 的片段, a b a、b 相同与否得到的答案不一样。
可以用 d p dp 求解。 d p [ i ] [ j ] dp[i][j] j = 0 j=0 表示与左右不同, j = 1 j=1 表示与左不同, j = 2 j=2 表示与右不同。
对于左右不同的情况,转移是:
d p [ i ] [ 0 ] = d p [ i 1 ] [ 1 ] ( k 2 ) + d p [ i 1 ] [ 2 ] ( k 2 ) + d p [ i 1 ] [ 0 ] ( k 3 ) dp[i][0]=dp[i-1][1]*(k-2)+dp[i-1][2]*(k-2)+dp[i-1][0]*(k-3)
d p [ i ] [ 1 ] = d p [ i 1 ] [ 2 ] + d p [ i 1 ] [ 0 ] dp[i][1]=dp[i-1][2]+dp[i-1][0]
d p [ i ] [ 2 ] = d p [ i 1 ] [ 1 ] + d p [ i 1 ] [ 0 ] dp[i][2]=dp[i-1][1]+dp[i-1][0]
答案为 d p [ l e n ] [ 1 ] + d p [ l e n ] [ 0 ] dp[len][1]+dp[len][0]

左右相同的时候比较简单,就不阐述了。
答案为 d p [ l e n ] [ 1 ] dp[len][1]

我们再分别计算片段,开头可以看做是左右相同的,但是这一片段答案是 d p [ i ] [ 0 ] + d p [ i ] [ 1 ] dp[i][0]+dp[i][1] ,因为最左边没有其他元素。

如果片段中的 1 -1 0 0 呢,那么:
左右不同,则是 d p 1 [ 0 ] [ 0 ] + d p 1 [ 0 ] [ 1 ] dp1[0][0]+dp1[0][1] ,答案为 1 1
左右相同,则是 d p 2 [ 0 ] [ 0 ] dp2[0][0] ,答案为 0 0
符合要求。

#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define sf(x) scanf("%d",&x)
typedef long long ll;
using namespace std;

const ll mod = 998244353;
const int maxn = 2e5+500;

int n,k;
ll dp1[maxn][3],dp2[maxn][2];
vector<int>odd,even;
int A[maxn];

int main(){
    cin>>n>>k;
    dp1[0][1]=1;
    dp1[0][0]=dp1[0][2]=0;
    for(int i=1;i<=200050;i++){
        dp1[i][0]=(dp1[i-1][1]*(k-2))%mod;
        dp1[i][0]=(dp1[i][0]+dp1[i-1][2]*(k-2))%mod;
        if(k>=3)dp1[i][0]=(dp1[i][0]+dp1[i-1][0]*(k-3))%mod;
        dp1[i][1]=(dp1[i-1][2]+dp1[i-1][0])%mod;
        dp1[i][2]=(dp1[i-1][1]+dp1[i-1][0])%mod;
    }
    dp2[0][1]=1;
    dp2[0][0]=0;
    for(int i=1;i<=200050;i++){
        dp2[i][0]=(dp2[i][0]+dp2[i-1][1]*(k-1))%mod;
        dp2[i][0]=(dp2[i][0]+dp2[i-1][0]*(k-2))%mod;
        dp2[i][1]=(dp2[i-1][0])%mod;
    }
    ll l=0,r=0;
    FOR(i,1,n){
        scanf("%d",&A[i]);
        if(i%2){
            if(A[i]!=-1)odd.push_back(i);
        }
        else{
            if(A[i]!=-1)even.push_back(i);
        }
    }
    if(odd.size()){
        l=(dp2[odd[0]/2][0]+dp2[odd[0]/2][1])%mod;
        //cout<<l<<endl;
        for(int i=0;i<odd.size()-1;i++){
            int diff=odd[i+1]-odd[i];
            diff=diff/2-1;
           // cout<<diff<<endl;
            if(A[odd[i]]==A[odd[i+1]]){
                l=(l*dp2[diff][0])%mod;
            }
            else{
                l=(l*(dp1[diff][0]+dp1[diff][1])%mod)%mod;
            }
        }
        int g=(n-odd[odd.size()-1])/2;
        if(g){
            l=(l*(dp2[g][0]+dp2[g][1])%mod)%mod;
        }
       // cout<<l<<endl;
    }
    else{
        l=k;
        for(int i=3;i<=n;i+=2)l=(l*(k-1))%mod;
    }
    if(even.size()){
        r=(dp2[even[0]/2-1][0]+dp2[even[0]/2-1][1])%mod;
        for(int i=0;i<even.size()-1;i++){
            int diff=even[i+1]-even[i];
            diff=diff/2-1;
            if(A[even[i]]==A[even[i+1]]){
                r=(r*dp2[diff][0])%mod;
            }
            else{
                r=(r*(dp1[diff][0]+dp1[diff][1])%mod)%mod;
            }
        }
        //cout<<r<<endl;
        int g=(n-even[even.size()-1])/2;
        if(g){
            r=(r*(dp2[g][0]+dp2[g][1])%mod)%mod;
        }
        //cout<<r<<endl;
    }
    else{
        r=k;
        for(int i=4;i<=n;i+=2)r=(r*(k-1))%mod;
    }
    cout<<(l*r)%mod<<endl;
}

发布了203 篇原创文章 · 获赞 17 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/mxYlulu/article/details/104262107