您的位置:首页 > 其它

[BZOJ1009][HNOI2008]GT考试

2018-01-25 10:37 357 查看
BZOJ

Luogu

GT考试=搞颓考试

sol

先考虑\(O(nm)\)的转移。设\(f_{i,j}\)表示填了\(i\)个数,当前在\(AC\)自动机上编号为\(j\)的节点上的方案数。

发现每次从\(f_i\)转移到\(f_{i+1}\)的转移都是一样的,所以可以矩阵快速幂优化\(DP\)转移,复杂度\(O(m^3\log{n})\)

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 100;
int n,m,mod,tot,len,ch[26]
,fail
,frb
,ans;
char s
;
queue<int>Q;
struct matrix{
int a

;
matrix(){memset(a,0,sizeof(a));}
int *operator [](int x){return a[x];}
matrix operator * (matrix b)
{
matrix c;
for (int i=0;i<=tot;i++)
for (int j=0;j<=tot;j++)
for (int k=0;k<=tot;k++)
(c[i][k]+=1ll*a[i][j]*b[j][k]%mod)%=mod;
return c;
}
}S,T;
void Insert()
{
scanf("%s",s);len=strlen(s);
int x=0;
for (int i=0;i<len;i++)
x=ch[s[i]-'0'][x]=++tot;
frb[x]=1;
}
void Get_Fail()
{
for (int i=0;i<10;i++) if (ch[i][0]) Q.push(ch[i][0]);
while (!Q.empty())
{
int u=Q.front();Q.pop();
for (int i=0;i<10;i++)
if (ch[i][u]) fail[ch[i][u]]=ch[i][fail[u]],Q.push(ch[i][u]);
else ch[i][u]=ch[i][fail[u]];
frb[u]|=frb[fail[u]];
}
}
int main()
{
scanf("%d %d %d",&n,&m,&mod);
Insert();
Get_Fail();
for (int i=0;i<=tot;i++)
if (!frb[i])
for (int j=0;j<10;j++)
if (!frb[ch[j][i]])
T[i][ch[j][i]]++;
S[0][0]=1;
while (n)
{
if (n&1) S=S*T;
T=T*T;n>>=1;
}
for (int i=0;i<=tot;i++) (ans+=S[0][i])%=mod;
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: