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;
    }
    
    
    
  • 相关阅读:
    批量数据导入数据库方法
    Remoting简单实践
    js面向对象继承
    Linq实现t-Sql的各种连接
    数据库树状结构的关系表的删除方案
    记录一次SQL查询语句
    mvc请求过程总结
    T-sql表表达式
    各个浏览器的兼容问题及样式兼容处理(不定期补充)
    vue.js 键盘enter事件的使用
  • 原文地址:https://www.cnblogs.com/mollnn/p/13577688.html
Copyright © 2011-2022 走看看