CF1140E Palindrome-less Arrays

我觉得这道题非常有前途.......

题意:给定一个填了一半的数组,你要把它补完,使之不存在奇回文串,求方案数。字符集为k。

n,k<=20w

解:不能有长为三的回文串。也就是不能有两个相隔1的数相同。

发现奇偶下标互相独立,抽出来就是不能有两个相邻的数相同。

我们可以设f[i][0]表示第i位填的跟之后第一个非空位置不同的方案数,f[i][1]是相同。

转移的时候,反正我个大SB分8类分类讨论,还要考虑后面没有非空位置的情况......

 1 #include <bits/stdc++.h>
 2 
 3 typedef long long LL;
 4 const int N = 200010;
 5 const LL MO = 998244353;
 6 
 7 int a[N], n, k, nex[N];
 8 LL f[N][2];
 9 
10 int main() {
11     int cnt = 0;
12     scanf("%d%d", &n, &k);
13 
14     for(int i = 1; i <= n; i++) {
15         scanf("%d", &a[i]);
16         if(i >= 3 && a[i] == a[i - 2] && a[i] != -1) {
17             puts("0");
18             return 0;
19         }
20     }
21 
22 
23     for(int i = n; i >= 1; i--) {
24         if(a[i] != -1) nex[i] = a[i];
25         else nex[i] = nex[i + 2];
26     }
27     LL ans = 1;
28     f[0][0] = f[0][1] = 1;
29     for(int i = 1; i <= n; i += 2) {
30         if(a[i] != -1) continue;
31         if(i - 2 < 1 && i + 2 > n) {
32             ans *= k;
33         }
34         else if(i - 2 < 1 && a[i + 2] == -1) {
35             f[i][0] = nex[i] ? k - 1 : k;
36             f[i][1] = nex[i] ? 1 : 0;
37         }
38         else if(i - 2 < 1) {
39             ans = ans * (k - 1) % MO;
40         }
41         else if(i + 2 > n && a[i - 2] == -1) {
42             ans = ans * f[i - 2][0] % MO * (k - 1) % MO;
43         }
44         else if(i + 2 > n) {
45             ans = ans * (k - 1) % MO;
46         }
47         else if(a[i + 2] != -1 && a[i - 2] != -1) {
48             ans = ans * (a[i - 2] == a[i + 2] ? k - 1 : k - 2) % MO;
49         }
50         else if(a[i - 2] != -1 && a[i + 2] == -1) {
51             f[i][0] = ((a[i - 2] == nex[i] || !nex[i]) ? k - 1 : k - 2);
52             f[i][1] = ((a[i - 2] == nex[i] || !nex[i]) ? 0 : 1);
53         }
54         else if(a[i - 2] == -1 && a[i + 2] != -1) {
55             ans = ans * ((f[i - 2][0] * (k - 2) % MO + f[i - 2][1] * (k - 1) % MO) % MO) % MO;
56         }
57         else {
58             f[i][0] = (f[i - 2][1] * (k - 1) % MO + f[i - 2][0] * (nex[i] ? k - 2 : k - 1) % MO) % MO;
59             f[i][1] = nex[i] ? f[i - 2][0] : 0;
60         }
61     }
62     LL temp = ans; ans = 1;
63     for(int i = 2; i <= n; i += 2) {
64         if(a[i] != -1) continue;
65         if(i - 2 < 1 && i + 2 > n) {
66             ans *= k;
67         }
68         else if(i - 2 < 1 && a[i + 2] == -1) {
69             f[i][0] = nex[i] ? k - 1 : k;
70             f[i][1] = nex[i] ? 1 : 0;
71         }
72         else if(i - 2 < 1) {
73             ans = ans * (k - 1) % MO;
74         }
75         else if(i + 2 > n && a[i - 2] == -1) {
76             ans = ans * f[i - 2][0] % MO * (k - 1) % MO;
77         }
78         else if(i + 2 > n) {
79             ans = ans * (k - 1) % MO;
80         }
81         else if(a[i + 2] != -1 && a[i - 2] != -1) {
82             ans = ans * (a[i - 2] == a[i + 2] ? k - 1 : k - 2) % MO;
83         }
84         else if(a[i - 2] != -1 && a[i + 2] == -1) {
85             f[i][0] = ((a[i - 2] == nex[i] || !nex[i]) ? k - 1 : k - 2);
86             f[i][1] = ((a[i - 2] == nex[i] || !nex[i]) ? 0 : 1);
87         }
88         else if(a[i - 2] == -1 && a[i + 2] != -1) {
89             ans = ans * ((f[i - 2][0] * (k - 2) % MO + f[i - 2][1] * (k - 1) % MO) % MO) % MO;
90         }
91         else {
92             f[i][0] = (f[i - 2][1] * (k - 1) % MO + f[i - 2][0] * (nex[i] ? k - 2 : k - 1) % MO) % MO;
93             f[i][1] = nex[i] ? f[i - 2][0] : 0;
94         }
95     }
96 
97     printf("%lld
", ans * temp % MO);
98     return 0;
99 }
AC代码
原文地址:https://www.cnblogs.com/huyufeifei/p/10590003.html