#include<bits/stdc++.h>
using namespace std;
const long long mod=998244353;
long long f[200007][2],g[200007][2];
long long a[200007],b[200007],c[200007];
int n,k,cnt1,cnt2;
long long qpow(long long a,long long p){
    long long ans=1;
    while(p){
        if(p&1)
            ans=ans*a%mod;
        a=a*a%mod;
        p>>=1;
    }
    return ans;
}
long long solve(long long *a,int n,int k){
    for(int i=2;i<=n;i++)
        if(a[i]==a[i-1]&&a[i]!=-1)//一定有奇数回文串,无法构造出good串
            return 0;
    int p=0;
    for(int i=1;i<=n;i++)
        if(a[i]!=-1)
            p++;
    if(!p)
        return qpow(k-1,n-1)*k%mod;//第一个随意选,剩下的选择和前一个不同的
    else if(p==1)
        return qpow(k-1,n-1);//选的和相邻的不同的
    else{
        if(p==n)
            return 1;//没有构造余地,全部已经安排好了
        if(k==1)//构造不出,一定会存在1?1只羊这样的回文串
            return 0;
        long long res=1;
        int l=0,r=0;
        for(int i=1;i<=n;i++){
            if(a[i]!=-1){
                l=i+1;
                break;
            }
            res=res*(k-1)%mod;//-1只要构造和相邻的不同即可
        }
        for(int i=n;i;i--){
            if(a[i]!=-1){
                r=i;
                break;
            }
            res=res*(k-1)%mod;//-1只要构造和相邻的不同即可
        }
        long long tmp=0;
        long long last=a[l-1];//上一个已经确定的a[i]
        for(int i=l;i<=r;i++){
            if(a[i]!=-1){
                if(!tmp){//前一个也已经确定
                    last=a[i];//更新最新一个确定的a[i]后继续
                    continue;
                }
                if(a[i]!=last)//两端数字不同
                    res=res*f[tmp][0]%mod;
                else//两端数字相同
                    res=res*g[tmp][0]%mod;
                tmp=0;//归零
                last=a[i];//更新
            }
            else
                tmp++;//增加中间-1的长度
        }
        return res;
    }
}
int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    //f和g类似染色,预处理出除了两端不是-1中间全都是-1能有多少种安排情况
    f[1][0]=k-2;//表示两端数字不同时,第一维和结尾不同的方案数,k-2因为要和两边都不同
    f[1][1]=1;//表示两端数字不同时,第一维和结尾相同的方案数,1因为下一个就可以在和上一个相同的那一段中间插入一个
    g[1][0]=k-1;//表示两端数字相同时,第一维和结尾不同的方案数,k-1因为两边是相同的
    g[1][1]=0;//表示两端数字相同时,第一维和结尾相同的方案数,0因为下两个才可以在最初两边都插一个
    for(int i=2;i<=n/2+1;i++){//染色DP,分开讨论,每次在前面的情况后面加上一个
        f[i][0]=(f[i-1][0]*(k-2)%mod+f[i-1][1]*(k-1)%mod)%mod;
        f[i][1]=f[i-1][0];
        g[i][0]=(g[i-1][0]*(k-2)%mod+g[i-1][1]*(k-1)%mod)%mod;
        g[i][1]=g[i-1][0];
    }
    for(int i=1;i<=n;i+=2)
        b[++cnt1]=a[i];//分离出下标为奇数的a[i]
    for(int i=2;i<=n;i+=2)
        c[++cnt2]=a[i];//分离出下标为偶数的a[i]
    long long ans=solve(b,cnt1,k);
    ans=ans*solve(c,cnt2,k)%mod;
    printf("%lld",ans);
    return 0;
}

Educational Codeforces Round 62 (Rated for Div. 2)E(染色DP,构造,思维,组合数学)的更多相关文章

  1. Educational Codeforces Round 73 (Rated for Div. 2)D(DP,思维)

    #define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;long long a[300007],b[3 ...

  2. Educational Codeforces Round 69 (Rated for Div. 2)D(DP,思维)

    #include<bits/stdc++.h>using namespace std;int a[300007];long long sum[300007],tmp[300007],mx[ ...

  3. Educational Codeforces Round 102 (Rated for Div. 2) B. String LCM (构造,思维)

    题意:给你两个字符串\(a\)和\(b\),找出它们的\(lcm\),即构造一个新的字符串\(c\),使得\(c\)可以由\(x\)个\(a\)得到,并且可以由\(y\)个\(b\)得到,输出\(c\ ...

  4. Educational Codeforces Round 62 (Rated for Div. 2) Solution

    最近省队前联考被杭二成七南外什么的吊锤得布星,拿一场Div. 2恢复信心 然后Div.2 Rk3.Div. 1+Div. 2 Rk9,rating大涨200引起舒适 现在的Div. 2都怎么了,最难题 ...

  5. Educational Codeforces Round 62 (Rated for Div. 2)

    A. Detective Book 题意:一个人读书  给出每一章埋的坑在第几页可以填完 . 一个人一天如果不填完坑他就会一直看 问几天能把这本书看完 思路:模拟一下 取一下过程中最大的坑的页数  如 ...

  6. Educational Codeforces Round 62 (Rated for Div. 2) C 贪心 + 优先队列 + 反向处理

    https://codeforces.com/contest/1140/problem/C 题意 每首歌有\(t_i\)和\(b_i\)两个值,最多挑选m首歌,使得sum(\(t_i\))*min(\ ...

  7. Educational Codeforces Round 62 (Rated for Div. 2)C

    题目链接 :C. Playlist #include<bits/stdc++.h> using namespace std; #define maxn 300005 #define LL ...

  8. Educational Codeforces Round 62 (Rated for Div. 2) - C Playlist

    当时题意看错了...不过大致思路是对的,唯一没有想到的就是用优先队列搞这个东西,真是不该啊... 题意大概就是,有N首歌,N首歌有两个东西,一个是长度Ti,一个是美丽值Bi,你最多可以选择K首歌, 这 ...

  9. C. Playlist Educational Codeforces Round 62 (Rated for Div. 2) 贪心+优先队列

    C. Playlist time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...

随机推荐

  1. python学习(十) 自带电池

    10.1 模块 >>> import math >>> math.sin(0) 0.0 10.1.1 模块是程序 假设自己写的hello.py放在c:\python ...

  2. java的mysql初探

    在实现如下demo之前,要安装mysql的驱动mysql-connector-java-gpl-5.1.26.msi DEMO: /* * 简单数据库测试 * @李志杰 * 2013-8-4 */ p ...

  3. [原创]Spring boot 框架构建jsp web应用

    说明 Spring boot支持将web项目打包成一个可执行的jar包,内嵌tomcat服务器,独立部署 为支持jsp,则必须将项目打包为war包 pom.xml中设置打包方式 <packagi ...

  4. jquery-attr与prop

    问题:经常使用jQuery插件的attr方法获取checked属性值,获取的值的大小为未定义,此时可以用prop方法获取其真实值,下面介绍这两种方法的区别: 1.通过prop方法获取checked属性 ...

  5. CSS鼠标手势大全

    实例: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. ...

  6. 4-2 线程安全性-原子性-atomic-2

    AtomicReference和AtomicLong.AtomicInteger很像,方法也基本上是一样的,然后我们通过引用Integer来做一个简单的例子. com.mmall.concurrenc ...

  7. C++中内存区域的划分

    栈存储区 那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区.里面的变量通常是局部变量.函数参数等. 堆存储区(自由存储区) 那些由new或者malloc分配的内存块,他们的释放编译器 ...

  8. ubuntu14.04 使用笔记

    这是第二次安装使用ubuntu了,虽然上一次因为不习惯和不会使用一两天就放弃了,这次坚持的时间稍微长一点,目前ubuntu的基本使用也熟悉了.但是由于ubuntu上的应用太少,常用软件,比如QQ,Ph ...

  9. 一个虚拟机网络的XML描述

    <?xml version="1.0" encoding="utf-8"?> <VNET> <ID>1</ID> ...

  10. 70个HR面试题

    请你自我介绍一下你自己,      回答提示:一般人回答这个问题过于平常,只说姓名.年龄.爱好.工作经验,这些在简历上都有,其实,企业最希望知道的是求职者能否胜任工作,包括:最强的技能.最深入研究的知 ...