HDU 6942. CCPC Strings

链接

https://acm.hdu.edu.cn/showproblem.php?pid=6942

题意

长度为 $n$ 的只有 cp 的字符串,共有 $2^n$ 种不同的字符串,求所有字符串中不重叠的为 CCPC 的子串的总个数。

思路

$\begin{aligned}
f_n&=\sum_{i=1}^{n-3i>0}(-1)^{i-1}{(n-3i)2^{n-1-3i}}\
f_{n-3}&=\sum_{i=1}^{n-3-3i>0}(-1)^{i-1}{(n-3-3i)2^{n-4-3i}}\
f_n-f_{n-3}&=(n-3)2^{n-4}\
f_n&=(n-3)2^{n-4}+f_{n-3}
\end{aligned}$

构造矩阵得到递推公式:

$$\begin{bmatrix}
f_{n-1} & f_{n-2} & f_{n-3} & (n-3)2^{n-4} & 2^{n-3}
\end{bmatrix}
*
\begin{bmatrix}
0 & 1 & 0 & 0 & 0\
0 & 0 & 1 & 0 & 0\
-1 & 0 & 0 & 0 & 0\
1 & 0 & 0 & 2 & 0\
0 & 0 & 0 & 1 & 2\
\end{bmatrix}

\begin{bmatrix}
f_{n} & f_{n-1} & f_{n-2} & (n-2)2^{n-3} & 2^{n-2}
\end{bmatrix}$$

用矩阵快速幂加速

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <bits/stdc++.h>
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(),(x).end()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
using namespace std;
typedef double DB;
typedef long double LD;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<PII> VPII;
// head
const int N=5;
const LL MOD=1e9+7;
struct M {
LL a[N][N];
void clear() {memset(a,0,sizeof a);}
M() {clear();}
void init() {
clear();
for(int i=0;i<N;i++) a[i][i]=1;
}
M operator + (const M &T) const {
M ret;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
ret.a[i][j]=(a[i][j]+T.a[i][j])%MOD;
return ret;
}
M operator - (const M &T) const {
M ret;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
ret.a[i][j]=(a[i][j]-T.a[i][j]+MOD)%MOD;
return ret;
}
M operator * (const LL &v) const {
M ret;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++) if(a[i][j])
ret.a[i][j]=a[i][j]*v%MOD;
return ret;
}
M operator * (const M &T) const {
M ret;
for(int i=0;i<N;i++)
for(int k=0;k<N;k++) if(a[i][k])
for(int j=0;j<N;j++) if(T.a[k][j])
ret.a[i][j]=(ret.a[i][j]+a[i][k]*T.a[k][j]%MOD)%MOD;
return ret;
}
M operator ^ (LL b) const {
M ret,bas;
for(int i=0;i<N;i++) ret.a[i][i]=1;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
bas.a[i][j]=a[i][j];
while(b) {
if(b&1) ret=ret*bas;
bas=bas*bas;
b>>=1;
}
return ret;
}
void print() {
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
cout<<a[i][j]<<" \n"[j==N-1];
}
};
LL c[N][N]={0,1,0,0,0,
0,0,1,0,0,
-1,0,0,0,0,
1,0,0,2,0,
0,0,0,1,2};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;cin>>T;
M b;
memcpy(b.a,c,sizeof c);
while(T--) {
int n;cin>>n;
if(n<4) cout<<0<<'\n';
else {
M a;
a.a[0][3]=1;
a.a[0][4]=2;
cout<<((a*(b^(n-3))).a[0][0]+MOD)%MOD<<'\n';
}
}
return 0;
}