本题解很易懂!
原题地址
给你一个数 n n n和一个字符串 s s s,求符合长度为 n n n且在 s s s中连续的字符不能连续出现,即这个字符串中不能出现 s s s的连续子串,答案对 1 e 9 + 7 1e9+7 1e9+7取模。
n ≤ 1 e 15 n \le 1e15 n≤1e15
不难想到一个很暴力的
d
p
dp
dp:
设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]为长度为
i
i
i且当前字符为
j
j
j的合法字符串个数
(
m
o
d
1
e
9
+
7
)
(mod 1e9+7)
(mod1e9+7),不难推式子:
d
p
[
i
]
[
j
]
=
∑
k
=
1
26
d
p
[
i
−
1
]
[
k
]
∣
(
k
,
j
)
∉
s
dp[i][j]=\sum_{k=1}^{26}dp[i-1][k]|(k,j)\not\in s
dp[i][j]=k=1∑26dp[i−1][k]∣(k,j)∈s
∀
1
≤
i
≤
26
d
p
[
1
]
[
i
]
=
1
\forall_{1\le i \le 26}dp[1][i]=1
∀1≤i≤26dp[1][i]=1
a
n
s
=
∑
i
=
1
26
d
p
[
n
]
[
i
]
ans=\sum_{i=1}^{26}dp[n][i]
ans=i=1∑26dp[n][i]
时间复杂度
O
(
2
6
2
n
)
O(26^2n)
O(262n)?反正T飞。
我们珂以把上面的式子变一下,设
w
[
i
]
[
j
]
=
[
(
i
,
j
)
∉
s
]
w[i][j]=[(i,j)\not\in s]
w[i][j]=[(i,j)∈s],即若
(
i
,
j
)
(i,j)
(i,j)在
s
s
s中不连续,则
w
[
i
]
[
j
]
=
1
w[i][j]=1
w[i][j]=1,否则
w
[
i
]
[
j
]
=
0
w[i][j]=0
w[i][j]=0。
式子变成了:
d
p
[
i
]
[
j
]
=
∑
k
=
1
26
d
p
[
i
−
1
]
[
k
]
×
w
[
k
]
[
j
]
dp[i][j]=\sum_{k=1}^{26}dp[i-1][k]\times w[k][j]
dp[i][j]=k=1∑26dp[i−1][k]×w[k][j]
珂能你一开始没看懂,
d
p
[
i
−
1
]
[
k
]
×
w
[
k
]
[
j
]
dp[i-1][k] \times w[k][j]
dp[i−1][k]×w[k][j]是啥呢?
分析一下,若
(
k
,
j
)
∉
s
(k,j)\not \in s
(k,j)∈s,那么
w
[
k
]
[
j
]
=
1
w[k][j]=1
w[k][j]=1,
d
p
[
i
−
1
]
[
k
]
×
w
[
k
]
[
j
]
=
d
p
[
i
−
1
]
[
k
]
dp[i-1][k]\times w[k][j]=dp[i-1][k]
dp[i−1][k]×w[k][j]=dp[i−1][k],贡献为
d
p
[
i
−
1
]
[
k
]
dp[i-1][k]
dp[i−1][k],符合题意。
若
(
i
,
j
)
∈
s
(i,j)\in s
(i,j)∈s,则
w
[
k
]
[
j
]
=
0
w[k][j]=0
w[k][j]=0,贡献为
0
0
0。
你可能会说“时间复杂度并没有变…”
确实没有变,但是这个式子珂以优化了。
感觉这个式子像什么?对!矩阵乘法!!!
矩乘的板子是
c
[
i
]
[
j
]
=
a
[
i
]
[
k
]
×
b
[
k
]
[
j
]
(
k
≤
p
)
c[i][j]=a[i][k]\times b[k][j](k\le p)
c[i][j]=a[i][k]×b[k][j](k≤p)
我们建
n
n
n个
1
×
26
1\times 26
1×26的矩阵
F
1
,
F
2
,
F
3
,
⋯
F
n
F_1,F_2,F_3,\cdots F_n
F1,F2,F3,⋯Fn,分别代表
d
p
[
1
]
[
1
⋯
26
]
,
d
p
[
2
]
[
1
⋯
26
]
,
d
p
[
3
]
[
1
⋯
26
]
⋯
d
p
[
n
]
[
1
⋯
26
]
dp[1][1\cdots26],dp[2][1\cdots26],dp[3][1\cdots26]\cdots dp[n][1\cdots26]
dp[1][1⋯26],dp[2][1⋯26],dp[3][1⋯26]⋯dp[n][1⋯26]再建一个
26
∗
26
26*26
26∗26的矩阵
A
A
A具体含义见下面。
初始化:
F
1
=
[
1
1
1
1
⋯
1
]
(
26
个
1
)
F_1= \left[ \begin{matrix} 1 &1 &1 &1\cdots 1 \end{matrix} \right] (26个1)
F1=[1111⋯1](26个1)
A = [ w [ 1 ] [ 1 ] w [ 1 ] [ 2 ] w [ 1 ] [ 3 ] ⋯ w [ 1 ] [ 26 ] w [ 2 ] [ 1 ] w [ 2 ] [ 2 ] w [ 2 ] [ 3 ] ⋯ w [ 2 ] [ 26 ] ⋮ ⋮ ⋮ ⋱ ⋮ w [ 26 ] [ 1 ] w [ 26 ] [ 2 ] w [ 26 ] [ 3 ] ⋯ w [ 26 ] [ 26 ] ] A= \left[ \begin{matrix} w[1][1]&w[1][2]&w[1][3]&\cdots &w[1][26] \\ w[2][1]&w[2][2]&w[2][3] &\cdots&w[2][26] \\ \vdots &\vdots &\vdots &\ddots&\vdots \\ w[26][1]&w[26][2]&w[26][3]&\cdots &w[26][26] \end{matrix} \right] A=⎣⎢⎢⎢⎡w[1][1]w[2][1]⋮w[26][1]w[1][2]w[2][2]⋮w[26][2]w[1][3]w[2][3]⋮w[26][3]⋯⋯⋱⋯w[1][26]w[2][26]⋮w[26][26]⎦⎥⎥⎥⎤
不难推出
F
i
=
F
i
−
1
×
A
(
i
>
1
)
F_i=F_{i-1}\times A(i>1)
Fi=Fi−1×A(i>1)
然而模拟矩阵乘也会炸啊…
矩阵乘法是
O
(
2
6
3
)
O(26^3)
O(263)的时间复杂度,算上递推的
O
(
n
)
O(n)
O(n)就是
O
(
n
×
2
6
3
)
O(n\times 26^3)
O(n×263),惊,被暴力吊打!
然而还有一个神器,矩阵快速幂!
(不会快速幂的珂以退出补知识了)
我们知道矩乘是有分配律的,但是这个顺推的式子好像不像是矩阵快速幂的样子…
那么开始下面一波操作:
F
2
=
F
1
×
A
F_2=F_1\times A
F2=F1×A
F
3
=
F
2
×
A
F_3=F_2\times A
F3=F2×A
然后我们将上面求的
F
2
F_2
F2代入:
F
3
=
F
1
×
A
×
A
=
F
1
×
A
2
F_3=F_1\times A\times A=F_1\times A^2
F3=F1×A×A=F1×A2
F
4
=
F
3
×
A
=
F
1
×
A
3
F_4=F_3\times A=F_1\times A^3
F4=F3×A=F1×A3
⋮
\vdots
⋮
F
n
=
F
1
×
A
n
−
1
F_n=F_1\times A^{n-1}
Fn=F1×An−1
妙啊!
a
n
s
=
∑
i
=
1
26
F
n
(
1
,
i
)
ans=\sum_{i=1}^{26}F_n(1,i)
ans=i=1∑26Fn(1,i)
但是你会发现,如果只到这一步的话,最后还要算一个
F
1
×
A
n
−
1
F_1 \times A^{n-1}
F1×An−1,爆掉。
但其实,
∑
i
=
1
26
F
n
(
1
,
i
)
=
∑
i
=
1
26
∑
j
=
1
26
A
n
−
1
(
i
,
j
)
\sum_{i=1}^{26}F_n(1,i)=\sum_{i=1}^{26}\sum_{j=1}^{26} A^{n-1}(i,j)
i=1∑26Fn(1,i)=i=1∑26j=1∑26An−1(i,j)
? ? ? \color{red}??? ???
什么操作?
如果您的矩阵基础扎实,请跳过此步骤。
设
C
=
F
1
×
A
n
−
1
C=F_1\times A^{n-1}
C=F1×An−1,则
C
(
1
,
1
)
=
F
1
(
1
,
1
)
×
A
n
−
1
(
1
,
1
)
+
F
1
(
1
,
2
)
×
A
n
−
1
(
2
,
1
)
+
⋯
+
F
1
(
1
,
26
)
×
A
n
−
1
(
26
,
1
)
C(1,1)=F_1(1,1)\times A^{n-1}(1,1)+F_1(1,2)\times A^{n-1}(2,1) +\cdots +F_1(1,26)\times A^{n-1}(26,1)
C(1,1)=F1(1,1)×An−1(1,1)+F1(1,2)×An−1(2,1)+⋯+F1(1,26)×An−1(26,1)
因为
F
1
=
[
1
1
1
1
⋯
1
]
(
26
个
1
)
F_1= \left[ \begin{matrix} 1 &1 &1 &1\cdots 1 \end{matrix} \right] (26个1)
F1=[1111⋯1](26个1)
所以
C
(
1
,
1
)
=
A
n
−
1
(
1
,
1
)
+
A
n
−
1
(
2
,
1
)
+
⋯
+
A
n
−
1
(
26
,
1
)
C(1,1)=A^{n-1}(1,1)+A^{n-1}(2,1)+\cdots+ A^{n-1}(26,1)
C(1,1)=An−1(1,1)+An−1(2,1)+⋯+An−1(26,1)
其他点以此类推
发现
C
C
C矩阵的所有数的和就是
A
n
−
1
A^{n-1}
An−1矩阵的所有数的和。
这其实是矩阵的简单的游戏。
时间复杂度
O
(
2
6
3
l
o
g
n
)
O(26^3logn)
O(263logn),能过。
C
o
d
e
\color{blue}Code
Code:
# include <bits/stdc++.h>
using namespace std;
struct Martix
{
long long a[30][30];
}A;
unsigned long long n;
char s[100010];
const long long mod=1e9+7;
Martix operator *(const Martix &x,const Martix &y)
{
Martix ans;
for(int i=1;i<=26;i++) for(int j=1;j<=26;j++) ans.a[i][j]=0;
for(int i=1;i<=26;i++)
{
for(int j=1;j<=26;j++)
{
for(int k=1;k<=26;k++)
{
ans.a[i][j]=(ans.a[i][j]+(x.a[i][k]%mod)*(y.a[k][j]%mod)%mod)%mod;
ans.a[i][j]%=mod;
}
}
}
return ans;
}
Martix js(Martix x,long long n)
{
Martix ans;
for(int i=1;i<=26;i++)
{
for(int j=1;j<=26;j++)
{
ans.a[i][j]=0;
}
}
for(int i=1;i<=26;i++) ans.a[i][i]=1;
while(n)
{
if(n&1)
{
ans=ans*x;
n--;
}
x=x*x;
n>>=1;
}
return ans;
}
int main(void)
{
scanf("%llu%s",&n,&s);
for(int i=1;i<=26;i++)
{
for(int j=1;j<=26;j++)
{
A.a[i][j]=1;
}
}
for(int i=1;i<strlen(s);i++)
{
A.a[s[i-1]-'a'+1][s[i]-'a'+1]=0;
}
Martix ans=js(A,n-1) ;
long long tot=0;
for(int i=1;i<=26;i++)
{
for(int j=1;j<=26;j++)
{
// cout<<ans.a[i][j]<<" ";
tot=(tot%mod)+(ans.a[i][j]%mod)%mod;
}
//cout<<endl;
}
cout<<tot%mod<<endl;
return 0;
}