题意:给定一个没有填完的序列,数值为-1表示你可以用 1~k 中的数字去覆盖它,求将该序列填充后,不存在长度为奇数的回文串的方案数

分析:

  1. 使之不存在长度为奇数的回文串,只需要满足不存在长度为3的回文串即可。换句话说:\(a[i] \neq a[i+2]\) 对所有的 \(i\) 成立。可以发现 i 为奇数与 i 为偶数是互不影响的。所以可以把它划分为两个串

    1. 一个串由 $a_1,a_3,a_5, \dots $组成
    2. 另一个串由$ a_2,a_4,a_6,\dots$ 组成
  2. 现在问题转化为了:给定一个序列,将其数值为-1的位置换为1~k中的数字,使得序列中两两相邻数字不同的方案数。不妨换个角度想,任何一组连续的 -1(长度可以为0或1),两边都只有四种情况

    1. 两边都没有数字(即整个串都是-1)
    2. 两边中有一边没有没有(只有整个串的左右两端有这种情况)
    3. 两边的数字相同
    4. 两边的数字不同

    另外我们可以发现,前两种情况可以由后两种情况推出来,所以只需预处理把 0~ (n/2)+1长度的-1串的方案数都预处理出来,问题就迎刃而解了。

  3. 设\(d(i,j)\) 表示长度为 \(i\) 的 -1 串,j 为0 表示两边数字相同,为1表示两边数字不同时的方案数,\(d[0][0] = 0, d[0][1] = 1\), 有转移方程:

    • \(i\) 为奇数

      • \(d[i][0] = d[i/2][0]*d[i/2][0] + (k-1)*d[i/2][1]*d[i/2][1]\)
      • \(d[i][1] = d[i/2][0]*d[i/2][1]*2 + (k-2)*d[i/2][1]*d[i/2][1]\)
    • \(i\) 为偶数
      • \(d[i][0] = (k-1)*d[i-1][1]\)
      • \(d[i][1] = d[i-1][0] + (k-2)*d[i-1][1]%mod\)

对于 i 为奇数的情况,我们可以取出这个序列的中间位置 mid,当 -1 串两端数字相同且都等于 x 时,先假设mid数字与x相同,那就转换为了两个长度为 i/2,序列两端相同 的子问题,然后假设 mid 与 x不同,那么就有(k-1)种方法,可以同样转换成两个长度为 i/2 ,序列两端不同的子问题。当 -1 串两端数字不同时,同理。

预处理d数组之后,就可以对我们之前分好的奇偶串做处理了。思路就是记录上一个不为-1的位置。然后最后做一下特判,就可以得到正确答案了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353;
ll d[100010][2];
int a[100010],b[100010];
ll n,k;
ll solve(int *a,ll len){
ll res = 1;
ll last = 0;
for(ll i=1;i<=len;i++){
if(a[i] == -1)continue;
else{
if(i == 1){
last = i;continue;
}
if(last == 0){
res = res * (d[i-2][0] + (k-1)*d[i-2][1])%mod;
}
else{
if(a[i] == a[last]){
res = res * d[i-last-1][0]%mod;
}
else res = res * d[i-last-1][1]%mod;
}
last = i;
}
}
if(last==0){
res = k;
for(int i=2;i<=len;i++)res = (res*(k-1))%mod;
}
else if(last !=len){
res = res * (d[len-last-1][0] + (k-1)*d[len-last-1][1]%mod)%mod;
}
return res;
}
int main(){
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++){
if(i&1)scanf("%d",&a[(i+1)/2]);
else scanf("%d",&b[i/2]);
}
d[0][0] = 0;d[0][1] = 1;
for(int i=1;i<=(n+1)/2;i++){
if(i&1){
int len = i/2;
d[i][0] = (d[len][0] * d[len][0]%mod + (k-1) * d[len][1]%mod * d[len][1]%mod)%mod;
d[i][1] = (d[len][0] * d[len][1]%mod * 2%mod + (k-2) * d[len][1]%mod * d[len][1]%mod)%mod;
}
else{
d[i][0] = (d[i-1][1] * (k-1)) % mod;
d[i][1] = (d[i-1][0] + (k-2) * d[i-1][1]%mod)%mod;
}
}
printf("%lld\n",(solve(a,(n+1)/2)*solve(b,n-(n+1)/2))%mod);
return 0;
}

CF-1140 E - Palindrome-less Arrays的更多相关文章

  1. 不断更新的 ToDo-List

    有些事情要明着写出来才会去干. 这里是一个不断更新的 ToDo-List,大致按照重要度和列出时间排序,已经完成的会画上删除线. 主要着眼短期计划,其中的大部分事务应该在一周内解决,争取不做一只鸽子. ...

  2. 【NOIP2017提高A组模拟9.12】Arrays and Palindrome

    [NOIP2017提高A组模拟9.12]Arrays and Palindrome[SPJ] 题目 Description Input Output Sample Input 1 6 Sample O ...

  3. CF 335B - Palindrome 区间DP

    335B - Palindrome 题目: 给出一个字符串(均有小写字母组成),如果有长度为100的回文子串,输出该子串.否则输出最长的回文子串. 分析: 虽然输入串的长度比较长,但是如果存在单个字母 ...

  4. CF&&CC百套计划2 CodeChef December Challenge 2017 Chef and Hamming Distance of arrays

    https://www.codechef.com/DEC17/problems/CHEFHAM #include<cstdio> #include<cstring> #incl ...

  5. CF 1326 D. Prefix-Suffix Palindrome

    D. Prefix-Suffix Palindrome 题意 给一个字符串 s,求一个字符串 t,t 由 s 的某个前缀以及某个后缀拼接而成,且 t 是回文串,长度不能超过 s.输出最长的 t 分析 ...

  6. CF 335B. Palindrome(DP)

    题目链接 挺好玩的一个题,1Y... #include <cstdio> #include <cstring> #include <iostream> using ...

  7. 【CF】7 Beta Round D. Palindrome Degree

    manacher+dp.其实理解manacher就可以解了,大水题,dp就是dp[i]=dp[i>>1]+1如何满足k-palindrome条件. /* 7D */ #include &l ...

  8. 【agc001d】Arrays and Palindrome

    Portal -->agc001D Description 给你一个\(m\)个数的排列\(A\),这个\(A\)中元素的顺序可以随便调换,\(A\)中的元素的和为\(n\),现在要你构造一个数 ...

  9. Agc001_D Arrays and Palindrome

    传送门 题目大意 给定一个元素和为$N$的有$M$个数的序列$A$,请你可以$A$元素排列的顺序,并需要构造一个有$K$个($K$可以自己定)数的数列,使得任意一个长度为$N$的字符串,若满足:前$A ...

  10. AGC001 D - Arrays and Palindrome【构造】

    把回文串的相等关系连一下,发现最后要求的是一笔画问题 注意到奇数长度的中间有一个单独没有连线的,所以a数组至多有两个奇数值 如果没有奇数,那么b在最前面放一个1,然后把a[1]~a[m-1]放上去,这 ...

随机推荐

  1. 出现提示ERROR 1289 The 'InnoDB' feature is disabled; you need MySQL built with 'InnoDB' to have IT working

    关闭mysql数据库 在mysql的安装目录中找到my.ini文件找到skip-innodb,在前面加上#号保存,重启mysql服务 OK.

  2. D. Restructuring Company 并查集 + 维护一个区间技巧

    http://codeforces.com/contest/566/problem/D D. Restructuring Company time limit per test 2 seconds m ...

  3. 《深入理解java虚拟机》笔记(6)内存分配与回收策略

    一.垃圾回收日志说明 [GC[DefNew: 7307K->494K(9216K), 0.0043710 secs] 7307K->6638K(19456K), 0.0044894 sec ...

  4. PHP的时间函数strtotime

    时间加减 [php] view plaincopy <?php //获取本地 提取年份+1 $date=date("Y-m-d",mktime(0,0,0,date(&quo ...

  5. JS中void(0)的含义

    看别人些的JavaScript脚本可以看到这样的代码: <a href="javascript:doTest2();void(0);">here</a> 但 ...

  6. 使用 xib 设置 button 等款等高

    很多时候需要使用平分的控件来布局,当然xib中可以之间使用 UIToolBar 使用 UIBarButtonItem 添加弹簧即可完成平均分布 但是,直接使用 button 也可以实现平均布局

  7. Java基础:(三)运算

    一.参数传递 Java的参数是以值传递的形式传入方法中,而不是引用传递. 二.隐式类型转换 Java不能隐式执行向下转型,因为这会使精度降低:但是使用 += 运算符可以执行隐式类型转换. float ...

  8. 死磕 java并发包之LongAdder源码分析

    问题 (1)java8中为什么要新增LongAdder? (2)LongAdder的实现方式? (3)LongAdder与AtomicLong的对比? 简介 LongAdder是java8中新增的原子 ...

  9. Java技术面试汇总

    1.servlet执行流程 客户端发出http请求,web服务器将请求转发到servlet容器,servlet容器解析url并根据web.xml找到相对应的servlet,并将request.resp ...

  10. where whereis locate find 的用法

    1.where :where ifconfig.用来搜索命令,显示命令是否存在以及路径在哪 2.whereis:whereis vim .用来搜索程序名,而且只搜索二进制文件(参数-b).man说明文 ...