E. Palindrome-less Arrays

E. Palindrome-less Arrays

题意:给定一串数字  不确定的地方用-1 表示 确定的就有确切的数字  不能有大于1的奇回文串 问在-1的地方填数字  可以填1---k 有多少种填法

思路 :由不能有大于1的奇回文串 等价于 奇数序号的数字相邻不能相等 偶数序号的数字相邻不能相等 分解出来即可、

然后进行状态定义 dp[i][0/1]  表示i位置和下一个确定数字的数字相同的填法(第二维是1)  和不同的填法(第二维是0)

需要特殊处理开始和结尾 即 :- 1 -1 -1 -1 A      A表示已经确定的数字  开头的可能性为pow(k-1,有多少个1) 结尾类似

其余的确定数字之前的段可以提取出来分段dp 乘法原理乘起来即可

中间转移为 dp[i][1]=dp[i-1][0]

dp[i][0]=dp[i-1][0]*(k-2)+dp[i-1][1]*(k-1) 

这里其实就是分类讨论的思想 如果dp只有一维的话那么后面的数字就会影响前面 产生后效性 

那么怎么取消这种后效性呢?那就是对后面的数字进行分类讨论 相当于已经确定了后面的数字 

所以前面填数字的时候就可以根据分类讨论的类别来进行转移 就可以取消后效性了



#include<bits/stdc++.h>
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
#define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr)) 
#define F first 
#define S second
#define pii pair<long long  ,long long  >
#define mkp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
const ll mod=998244353;
long long  a[maxn];
long long  dp[maxn][2];
ll n,k;
vector<ll>even,odd;
vector<ll>even_div,odd_div;
long long solve(const vector<ll>&a,const vector<ll>&div,int flag){
    long long ans=1;
    if(div.size()==0){
        ans=k;
        ans%=mod;
        for(int i=1;i<a.size();i++){
            ans*=(k-1);
            ans%=mod;
        }
        return ans;
    }
    if(div[0]!=0){
        for(int i=0;i<div[0];i++){
            ans*=(k-1);
            ans%=mod;
        }
    }
    MS(dp,0);
    for(int z=0;z<div.size()-1;z++){
        //cout<<a[div[z]]<<" what ?  "<<a[div[z+1]]<<endl;
        if(a[div[z]]!=a[div[z+1]]){
            dp[div[z]][1]=0;
            dp[div[z]][0]=1;
        }
        else dp[div[z]][1]=1,dp[div[z]][0]=0;
    }
    for(int z=1;z<div.size();z++){
        //int zz=0;
        if(a[div[z-1]]!=a[div[z]])dp[div[z-1]][0]=1;
        for(int i=div[z-1]+1;i<div[z];i++){
    //        zz=1;
            //if(i!=div[z]-1)dp[i][0]=(((dp[i-1][1]+dp[i-1][0])%mod)*(k-1)%mod);
             dp[i][0]=(((dp[i-1][0]*(k-2)%mod)+(dp[i-1][1]*(k-1)%mod))%mod);
    //        cout<<i<<" ?? "<<dp[i-1][0]<<" *** "<<dp[i-1][1]<<endl;
            dp[i][1]=dp[i-1][0]%mod;
            
        }
        ans=((ans*dp[div[z]-1][0])%mod);
    }
    for(int i=div[div.size()-1]+1;i<a.size();i++){
        ans*=(k-1);
        ans%=mod;
    }
    //cout<<ans<<endl;
return ans;    
}
int main(){
    scanf("%lld%lld",&n,&k);
    FOR(i,1,n)scanf("%lld",&a[i]);
    for(int i=1;i<=n;i+=2){
        odd.push_back(a[i]);    
    }
    for(int i=2;i<=n;i+=2){
        even.push_back(a[i]);    
    }
    for(int i=0;i<odd.size();i++){
        if(odd[i]!=-1)odd_div.push_back(i);
        if(i!=0&&odd[i]==odd[i-1]&&odd[i]!=-1){
        cout<<0<<endl;
            return 0;
        }
        
    }
    for(int i=0;i<even.size();i++){
        if(i!=0&&even[i]==even[i-1]&&even[i]!=-1){
            cout<<0<<endl;
            return 0;
        }
        if(even[i]!=-1)even_div.push_back(i);
    }
    long long temp1,temp2;
    temp1=solve(odd,odd_div,1);
    temp2=solve(even,even_div,0);
    cout<<((temp1%mod)*(temp2%mod))%mod<<endl;
    return 0;
}

全部评论

相关推荐

03-02 02:44
门头沟学院 Java
咩咩子_:92直接梭哈
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务