zoukankan      html  css  js  c++  java
  • [CF1140E] Palindrome-less Arrays

    Description

    给定一个长度为 (n) 的数组,其中有些位置未定(可在 ([1,k]) 中任意取值),问有多少种填数的方案可以使得数组中不存在长度为奇数的回文子串。

    Solution

    即不存在长度为 (3) 的回文串

    即对任意 (i)(a_i eq a_{i+2})

    考虑分奇偶位处理,方案数相乘

    于是转化为相邻两位不相同的方案数

    考虑对于每一段连续的 (-1) 分别处理

    (f[i][0]) 表示长度为 (i)(-1) 段的左边和右边的元素相同的方案数,(f[i][1]) 为不同,则有

    [f[i][0]=(k-1) cdot f[i-1][1] \ f[i][1]=(k-2)cdot f[i-1][1] +f[i-1][0] ]

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N =  1000005;
    const int mod = 998244353;
    const int dbg = 0;
    
    int n,k,a[N],f[N][2],p[N],cnt,b[N];
    
    int qpow(int p,int q)
    {
        return (q&1 ? p : 1) * (q? qpow(p*p%mod,q/2) : 1) % mod;
    }
    
    void presolve()
    {
        f[0][0]=0; f[0][1]=1;
    
        for(int i=1;i<=n+1;i++)
        {
            f[i][0]=(k-1)*f[i-1][1];
            f[i][1]=(k-2)*f[i-1][1]+f[i-1][0];
            f[i][0]%=mod;
            f[i][1]%=mod;
        }
    }
    
    int solver(int n,int *a)
    {
        memset(p,0,sizeof p);
        cnt=0;
    
        for(int i=1;i<=n;i++) if(a[i]!=-1) p[++cnt]=i;
    
        a[0]=-2;
        a[n+1]=-2;
        p[++cnt]=n+1;
    
        if(dbg) for(int i=0;i<=2;i++)
        {
            cout<<"i="<<i<<" f[i][?]="<<f[i][0]<<","<<f[i][1]<<endl;
        }
    
        int ans=1;
        for(int i=1;i<=cnt;i++)
        {
            int len=p[i]-p[i-1]-1;
            if(dbg) cout<<len<<",";
            if(len>0)
            {
                if(dbg) cout<<"<"<<p[i-1]<<","<<p[i]<<"> ";
                if(a[p[i]]==-2 && a[p[i-1]]==-2) ans*=k*qpow(k-1,len-1)%mod, ans%=mod;
                else if(a[p[i]]==-2 || a[p[i-1]]==-2) ans*=qpow(k-1,len), ans%=mod;
                else if(a[p[i]]==a[p[i-1]]) ans*=f[len][0], ans%=mod;
                else ans*=f[len][1], ans%=mod;
            }
        }
    
        return ans;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n>>k;
        for(int i=1;i<=n;i++) cin>>a[i];
    
        for(int i=1;i<n-1;i++) if(a[i]!=-1 && a[i]==a[i+2])
        {
            cout<<0<<endl;
            return 0;
        }
    
        presolve();
    
        int len1=0,len2=0;
        for(int i=1;i<=n;i+=2) b[++len1]=a[i];
        int ans1=solver(len1,b);
        memset(b,0,sizeof b);
        for(int i=2;i<=n;i+=2) b[++len2]=a[i];
        int ans2=solver(len2,b);
        if(dbg) cout<<ans1<<":"<<ans2<<endl;
        cout<<ans1*ans2%mod<<endl;
    }
    
    
    
  • 相关阅读:
    Kafka 配置
    Zookeeper的Watcher机制
    Ubuntu18.04下希捷移动硬盘Seagate Backup Plus读写慢
    Spring Boot 使用Jar打包发布, 并使用 Embedded Jetty/Tomcat 容器
    再谈C#委托与事件
    C#委托和事件例析
    PHP:session无法使用
    C++:实现类似MFC的IsKindOf功能
    C++:复制构造函数
    C++:运算符重载
  • 原文地址:https://www.cnblogs.com/mollnn/p/13577688.html
Copyright © 2011-2022 走看看