cf 1160 E dp 组合数 思维

题意:给定一个数组,如果它含有长度>=3的回文数组,那就是不好的

  问通过将数组中的 -1 用【1,k】替代,有多少种可能,使这个数组是好数组。

思路:长度>=3的回文数组,都可以转化为==3的来看,所以整个数组不含有==3的回文数组

  也就是a[i]!=a[i+2] (  a[i]!=-1)

这样就可以奇偶分开来看了,将两者的组合撑起来就是答案

那么对形如   x..-1-1-1y..-1.z的序列,怎么判断可能呢?

分段来看就有4种可能:  -1..-1   -1....a (a...-1)    a.-1...a   a..-1...b

我们对后两种dp来做,d1[N][3]有三个状态  0 :a, 1 : b, 2 非a,b

这样就有了dp的思路 了

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(v) v.begin(),v.end()
#define mem(a) memset(a,0,sizeof(a))
#define bug printf("get 
");
const int N = 2e5+4;
const ll mod =998244353;
const int INF = 1e9+4;
const double eps = 1e-7;

int n,k;
vector<int>arr;
int a[N];
ll ans1,ans2;
ll d1[N][3],d2[N][2];//d1 : a....b d2 a...a
ll d3[N];

ll add(ll a,ll b){    return (a+b)%mod;}

ll sol(){
    for(int i=0;i+1<arr.size();++i)if(arr[i]!=-1 &&arr[i]==arr[i+1])return 0;
    int anot=0;
    for(auto x:arr)if(x!=-1)anot++;
    if(anot==0){
        ll res=k;
        for(int i=0;i+1<arr.size();++i){
            res =res*(k-1)%mod;
        }return res;
    }
    //printf("??");
    arr.pb(0);int las= 0;
    ll res=1;
    for(int i=0;i<arr.size();){
        int num =0;
        while(arr[i]==-1){
            num++;
            i++;
        }
        if(num){
            //cout<<"num: " <<num<<endl;
            if(las==0 ||arr[i]==0){
                res =res* d3[num]%mod;
            }
            else{
                if(las==arr[i])
                    res= res * (d1[num][1]+d1[num][2])%mod;
                else res = res * (d1[num][0]+d1[num][2])%mod;
            }
        }
        las= arr[i];
        i++;
    }
    //cout<<res<<endl;
    return res;
}

int main(){
    cin>>n>>k;
    d1[1][0] = 0;
    d1[1][1] = 1;//
    d1[1][2] = k-2;
    d2[1][0] = 0;//
    d2[1][1] =k-1;
    d3[1] = k-1;
    for(int i=2;i<=n;++i){
        d1[i][0] = add(d1[i-1][1],d1[i-1][2]);
        d1[i][1] = add(d1[i-1][0],d1[i-1][2]);
        //k==2???
        d1[i][2] = add( add(d1[i-1][0]*(k-2),d1[i-1][1]*(k-2))  ,d1[i-1][2]*(k-3));
        d2[i][0] = d2[i-1][1];// a
        d2[i][1] = add(d2[i-1][0]*(k-1) ,d2[i-1][1]*(k-2));//not a
        d3[i] = d3[i-1]*(k-1)%mod;
    }

    for(int i=1;i<=n;++i){cin>>a[i];}
    for(int i=1;i<=n;i+=2)
        arr.pb(a[i]);
    ans1=sol();
    arr.clear();
    for(int i=2;i<=n;i+=2)arr.pb(a[i]);
    ans2=sol();

   // printf("%lld %lld 
",ans1,ans2);

    cout<<ans1*ans2%mod<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/wjhstudy/p/10752930.html