[TJOI2019] 甲苯先生的字符串 题解
有点水了……
考虑相邻的不能放在一起,不相邻的可以,那么很容易想到转移方程:
\[dp_{i,j}=\sum_{k=0}^{25}dp_{i-1,k}[j,k不相邻]
\]
其中 \(dp_{i,j}\) 表示填了 \(i\) 位,最后一位填 \(j\)。
那结合数据范围,显然矩阵快速幂。
时间复杂度 \(O(26^3\log n)\),可以通过
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int p=1e9+7;
struct mat{
int c[26][26];
mat(){memset(c,0,sizeof(c));}
}dp,ans;int re;
char s[N];long long n;
mat operator*(mat x,mat y){
mat z;
for(int i=0;i<26;i++)
for(int j=0;j<26;j++)
for(int k=0;k<26;k++)
z.c[i][j]=(z.c[i][j]+1ll*x.c[i][k]*y.c[k][j]%p)%p;
return z;
}mat operator^(mat x,long long y){
mat z;
for(int i=0;i<26;i++)
z.c[i][i]=1;
while(y){
if(y&1) z=z*x;
x=x*x,y>>=1;
}return z;
}int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>s,n--;
for(int i=0;i<26;i++)
for(int j=0;j<26;j++)
dp.c[i][j]=1;
for(int i=1;s[i];i++)
dp.c[s[i-1]-'a'][s[i]-'a']=0;
for(int i=0;i<26;i++) ans.c[0][i]=1;
ans=ans*(dp^n);
for(int i=0;i<26;i++)
re=(re+ans.c[0][i])%p;
cout<<re;
return 0;
}