zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    顶点与片段着色器的例子
    Unity cg vertex and fragment shaders(二)
    Unity cg vertex and fragment shaders(一)
    C#线程(一)
    shell脚本变量定义注意别跟系统变量重名了……
    VLC编译问题
    VIM技巧:翻页
    Linux命令:cd
    Linux设置:环境变量
    VIM技巧:显示行号
  • 原文地址:https://www.cnblogs.com/wjhstudy/p/10752930.html
Copyright © 2011-2022 走看看