题意:给出n个单词,求这些单词能组成的文章个数,文章的单词数L个。
题解:
各种TL,一个黑色的晚上。不知道为什么,自己写的矩阵乘法异常的慢,从类改成写简陋的C格式,都TL了,发现是取模太多次的缘故,于是改成加完在摸,结果wa了,坑爹,然后改成longlong TL了,简直无情啊。最后用了无符号int即不会爆int也不像longlong那么耗费时间。于是就过了。。。。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define B(x) (1<<(x)) typedef long long ll; //typedef unsigned __int64 Ull; const int oo=0x3f3f3f3f; //const ll OO=1LL<<61; const int MOD=10007; const int maxn=1005; const int SIZE=70; const int type=26; char str[10]; unsigned maze[SIZE][SIZE],temp[SIZE][SIZE],res[SIZE][SIZE]; int n; void Copy(unsigned x[][SIZE],unsigned y[][SIZE]) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) x[i][j]=y[i][j]; } void Matrix_Mul(unsigned x[][SIZE],unsigned y[][SIZE]) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) { temp[i][j]=0; for(int k=0;k<n;k++) temp[i][j]+=x[i][k]*y[k][j]; temp[i][j]%=MOD; } } void Matrix_pow(unsigned x[][SIZE],int k) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) res[i][j]=(i==j); while(k) { if(k&1) { Matrix_Mul(res,x); Copy(res,temp); } Matrix_Mul(x,x); Copy(x,temp); k>>=1; } } int quick_pow(int a,int k) { int ans=1; while(k) { if(k&1) ans=ans*a%MOD; a=a*a%MOD; k>>=1; } return ans; } struct ACautomaton { int next[SIZE][type],fail[SIZE],word[SIZE]; int cnt,root; int newNode() { for(int i=0;i<type;i++) next[cnt][i]=-1; word[cnt++]=0; return cnt-1; } void Init() { cnt=0; root=newNode(); } void Insert(char buff[]) { int now=root; int len=strlen(buff); for(int i=0,k;i<len;i++) { k=buff[i]-'A'; if(next[now][k]==-1) next[now][k]=newNode(); now=next[now][k]; } word[now]=1; } void build() { fail[root]=root; int now=root; queue<int>Q; for(int i=0;i<type;i++) { if(next[now][i]==-1) next[now][i]=root; else { fail[next[now][i]]=root; Q.push(next[now][i]); } } while(!Q.empty()) { now=Q.front(); Q.pop(); if(word[fail[now]]) word[now]=1; for(int i=0;i<type;i++) { if(next[now][i]==-1) next[now][i]=next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; Q.push(next[now][i]); } } } } int solve(int L) { n=cnt; for(int i=0;i<n;i++) for(int j=0;j<n;j++) maze[i][j]=0; for(int i=0;i<cnt;i++) for(int j=0;j<type;j++) { int k=next[i][j]; if(!word[k]) maze[i][k]++; } Matrix_pow(maze,L); int ans=0; for(int i=0;i<n;i++) ans=(ans+res[0][i]+MOD)%MOD; int sum=quick_pow(26,L); return (sum-ans+MOD)%MOD; } }ac; int main() { int N,L; while(scanf("%d %d",&N,&L)!=EOF) { ac.Init(); for(int i=1;i<=N;i++) { scanf("%s",str); ac.Insert(str); } ac.build(); printf("%d\n",ac.solve(L)); } return 0; }