P5337 [TJOI2019]甲苯先生的字符串
显而易见有一个记录末尾字母的 \(O(n)\) 递推。
显而易见可以用矩阵快速幂优化,不妨用一个 \(1\times 26\) 的矩阵维护当前 DP 值,初始化为:
\[\begin{bmatrix}
1&1&1\cdots 1&1&1
\end{bmatrix}\]
构造一个 \(26\times 26\) 的转移矩阵,如果 \(i\) 不能转移到 \(j\) 那么 \((j,i)=0\) 否则 \((j,i)=1\),这个根据矩阵乘法定义来。
然后就做完了,记得开 long long
,时间复杂度 \(O(\log n)\)。
code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define N 26
#define Mod 1000000007
#define For(i,x,y)for(i=x;i<=(y);i++)
ll n;
string s1;
namespace Subtask1
{
bool bo[N][N];
int f[2][100005];
void init()
{
int i,j,k;
For(i,0,s1.size()-2)bo[s1[i]-'a'][s1[i+1]-'a']=1;
For(i,0,25)f[1][i]=1;
For(i,2,n)
{
For(j,0,25)
For(k,0,25)
if(!bo[j][k])f[i&1][k]=(f[i&1][k]+f[i&1^1][j])%Mod;
For(j,0,25)f[i&1^1][j]=0;
}
For(k,1,25)f[n&1][0]=(f[n&1][0]+f[n&1][k])%Mod;
cout<<f[n&1][0];
}
}
namespace Subtask2
{
struct matrix
{
int g[N][N];
}a,b,c;
matrix mul(matrix p,matrix q)
{
int i,j,k;
For(i,0,25)
For(j,0,25)
{
c.g[i][j]=0;
For(k,0,25)c.g[i][j]=(c.g[i][j]+1LL*p.g[i][k]*q.g[k][j])%Mod;
}
return c;
}
void init()
{
int ans=0,i,j;
For(i,0,25)
{
For(j,0,25)b.g[i][j]=1;
a.g[0][i]=1;
}
For(i,0,s1.size()-2)b.g[s1[i]-'a'][s1[i+1]-'a']=0;
n--;
while(n)
{
if(n&1)a=mul(a,b);
b=mul(b,b);
n>>=1;
}
For(i,0,25)ans=(ans+a.g[0][i])%Mod;
cout<<ans;
}
}
int main()
{
// freopen("str.in","r",stdin);
// freopen("str.out","w",stdout);
int i;
cin>>n>>s1;
if(n>100000)Subtask2::init();
else Subtask1::init();
return 0;
}