[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;
} 
posted @ 2024-10-14 19:41  长安一片月_22  阅读(7)  评论(0编辑  收藏  举报