题意:给你一个数组,如果数组中的某个位置是-1那就可以填1到m的数字中的一个,但是要遵守一个规则:不能出现长度为奇数回文的子串,问合法的填法有多少种?

思路:不出现长度为奇数的回文子串,只需不出现长度为3的回文子串就可以了,那么i位置和i - 2位置填的数字不能一样。所以,我们可以把这个数组拆成2部分,所有的奇数位置和所有的偶数位置分别成一个串,之后吧两个串的答案乘起来就是答案了。每个串肯定是下列情况中的一种或多种构成。

1:全是-1, 那么明显有k * (k - 1) ^ (n - 1)种答案。

2:有一遍是大于0的数,假设长度为n,那么答案就是(k - 1) ^ n。

3:两边都是大于0的数,这个需要DP预处理后得到答案。

设dp[i][0 / 1]表示长度为i的-1串,当前最后一个-1填的数字与最前面的数字不同/相同,合法的方案数。

转移是这样:dp[i][1] = dp[i - 1][0], 因为i - 1位置填的数字与最前面的不同,所有填一个与最前面位置相同的数字是合法的,所有直接转移。

dp[i][0] = (k - 1) * dp[i - 1][1] + (k - 2) * dp[i - 1][0],前半部分很好理解,加上一个和最前面不等的数就可以了。后半部分,每个数不能和最前面相等,也不能和自己相等,所有是k - 2个转移。

代码:

  1. #include <bits/stdc++.h>
  2. #define LL long long
  3. using namespace std;
  4. const LL mod = 998244353ll;
  5. const int maxn = 200010;
  6. LL dp[maxn][2];
  7. LL a[maxn], b[maxn];
  8. int tot = 0;
  9. LL m;
  10. int n;
  11. LL qpow(LL x, LL y) {
  12. LL ans = 1;
  13. for (; y; y >>= 1) {
  14. if(y & 1) ans = (ans * x) % mod;
  15. x = (x * x) % mod;
  16. }
  17. return ans;
  18. }
  19. LL solve() {
  20. int pos = 1, cnt = 0;
  21. LL ans = 1;
  22. while(pos <= tot) {
  23. while(a[pos] > 0 && pos <= tot) {
  24. if(pos > 1 && a[pos] == a[pos - 1]) return 0;
  25. pos++;
  26. }
  27. int pre = pos - 1;
  28. while(a[pos] < 0 && pos <= tot) {
  29. pos++;
  30. cnt++;
  31. }
  32. if(pre == 0 && pos == tot + 1) return (m * qpow(m - 1, tot - 1)) % mod;
  33. else if(pre == 0 || pos == tot + 1) ans = (ans * qpow(m - 1, pos - pre - 1)) % mod;
  34. else {
  35. int flag = (int)(a[pre] == a[pos]);
  36. if(flag == 1)
  37. ans = (ans * dp[pos - pre - 1][0]) % mod;
  38. else {
  39. LL tmp = (dp[pos - pre - 1][1] + (((dp[pos - pre - 1][0] * qpow(m - 1, mod - 2)) % mod) * (m - 2)) % mod) % mod;
  40. ans = (ans * tmp) % mod;
  41. }
  42. }
  43. }
  44. return ans;
  45. }
  46. int main() {
  47. scanf("%d%lld", &n, &m);
  48. for (int i = 1; i <= n; i++) {
  49. scanf("%lld", &b[i]);
  50. }
  51. dp[1][0] = m - 1;
  52. dp[1][1] = 0;
  53. for (int i = 2; i <= n; i++) {
  54. dp[i][0] = ((dp[i - 1][1] * (m - 1)) % mod + (dp[i - 1][0] * (m - 2)) % mod) % mod;
  55. dp[i][1] = dp[i - 1][0];
  56. }
  57. LL ans1, ans2;
  58. for (int i = 1; i <= n; i += 2)
  59. a[++tot] = b[i];
  60. ans1 = solve();
  61. tot = 0;
  62. for (int i = 2; i <= n; i += 2)
  63. a[++tot] = b[i];
  64. ans2 = solve();
  65. printf("%lld\n", (ans1 * ans2) % mod);
  66. }

  

Codeforces 1140E DP的更多相关文章

  1. Two Melodies CodeForces - 813D (DP,技巧)

    https://codeforces.com/problemset/problem/813/D dp[i][j] = 一条链以i结尾, 另一条链以j结尾的最大值 关键要保证转移时两条链不能相交 #in ...

  2. Consecutive Subsequence CodeForces - 977F(dp)

    Consecutive Subsequence CodeForces - 977F 题目大意:输出一序列中的最大的连续数列的长度和与其对应的下标(连续是指 7 8 9这样的数列) 解题思路: 状态:把 ...

  3. codeforces 1140E Palindrome-less Arrays

    题目链接:http://codeforces.com/contest/1140/problem/E 题目大意: 如果一个数组的存在一个奇数长的回文就不好. 不是不好的数组是好的. 你可以把-1用1到k ...

  4. codeforces的dp专题

    1.(467C)http://codeforces.com/problemset/problem/467/C 题意:有一个长为n的序列,选取k个长度为m的子序列(子序列中不能有位置重复),求所取的k个 ...

  5. Codeforces 721C [dp][拓扑排序]

    /* 题意:给你一个有向无环图.给一个限定t. 问从1点到n点,在不超过t的情况下,最多可以拜访几个点. 保证至少有一条路时限不超过t. 思路: 1.由无后向性我们可以知道(取决于该图是一个DAG), ...

  6. CodeForces 607C (DP) Hard problem

    题目:这里 题意:给定n个字符串,每个字符串可以进行一项操作,就是将这个字符串交换,就是该字符串的第一个和最后一个交换,第二个和倒数第二个交换,以此类推,当然可以选择对于 该字符串进行或不进行这项操作 ...

  7. Codeforces 611d [DP][字符串]

    /* 题意:给一个长度不超过5000的字符串,每个字符都是0到9的数字. 要求将整个字符串划分成严格递增的几个数字,并且不允许前导零. 思路: 1.很开心得发现,当我在前i个区间以后再加一个区间的时候 ...

  8. Codeforces 404D [DP]

    /* 我是一个习惯后悔,但是没办法忍受内疚感的二货== 这题是个无脑dp,但是比赛大概20min没出...其实最后5min我好好想想简单化边界条件,可以出的. 题意: 给你一个长度为1e6的由?*01 ...

  9. Codeforces 119C DP

    题意: 有n天,m门课和常数k; 每天上一门课,每门课程有两个属性,最少作业量a,最多作业量b,和难度c. 1<=a<=b<=1e16 c<=100 1<=n<=m ...

随机推荐

  1. Joda-Time 入门

    Joda-Time 令时间和日期值变得易于管理.操作和理解.事实上,易于使用是 Joda 的主要设计目标.其他目标包括可扩展性.完整的特性集以及对多种日历系统的支持.并且 Joda 与 JDK 是百分 ...

  2. mysql的一些语法

    alter table S61.T6198 modify  F12 varchar(30) DEFAULT NULL COMMENT '流水号'; 修改表字段结构. mysql不支持top ,只支持l ...

  3. 使用python+ffmpeg批量转换格式

    需求:  给定一个文件夹路径,遍历该文件夹内的所有文件以及子文件夹内的文件,当所有后缀名为wav格式的文件转换为ogg格式的文件. import os # 获取目录下的所有文件列表 import fn ...

  4. UICollectionView中的cell包含UIScrollview

    需求:在scrollview的子View不为0,当scrollview的展示的index不为0且向右滑动CollectionView.CollectionView不滑动Cell,而是让scrollvi ...

  5. 一、基础项目构建,引入web模块,完成一个简单的RESTful API

    一.Spring Boot的主要优点: 为所有Spring开发者更快的入门 开箱即用,提供各种默认配置来简化项目配置 内嵌式容器简化Web项目 没有冗余代码生成和XML配置的要求 二.使用maven构 ...

  6. AtomicInteger 、Synchronized 和 volatile 之间的区别?

    AtomicInteger:无锁的线程安全整数??? Synchronized:同步 volatile:挥发性??? 参考文档:

  7. 设置overflow:auto无效的解决办法

    做项目中经常要用到滚动条,有时候给div设置overflow无效. 遇到这样的问题,只需要在 F12 Elements面板检查一下要设置overflow的元素的宽高是否大于父级元素宽高. (overf ...

  8. fastDFS配置文件 fdfs_client.conf

    # connect timeout in seconds# default value is 30sconnect_timeout=30 # network timeout in seconds# d ...

  9. C#中的类型相等与恒等(Equality & Identity)

    l  Equality:如果两个对象是相同的类型,并且它们各自带有相同和等值的属性.(They are instances of the same type and if each of the fi ...

  10. AcWing 197. 阶乘分解 (筛法)打卡

    给定整数 N ,试把阶乘 N! 分解质因数,按照算术基本定理的形式输出分解结果中的 pipi 和 cici 即可. 输入格式 一个整数N. 输出格式 N! 分解质因数后的结果,共若干行,每行一对pi, ...