两个题差不多,只不过hdu上的恶心一点,对2^64取模,其实就相当于不用取模,所有的数都用unsigned __int64 即可,注意,无符号类型6-9就不是-3了哦
经典矩阵乘法是指求A+A^2+A^3+A^4+....A^n
做法在这里http://blog.csdn.net/haha593572013/article/details/8001943
然后这两题主要要做的就是构造trie图,继而构造出初始矩阵,mat[i][j]表示i走到j有几种走法 ,这个矩阵自乘n次之后就表示i走到j走n步有几种走法
hdu 2243
#include<cstdio>
#include<cstring>
typedef unsigned __int64 ULL;
const int MAX = 65;
int n,k,m,tn;
struct Mat {
ULL mat[MAX][MAX];
friend Mat operator *(Mat a,Mat b);
friend Mat operator +(Mat a,Mat b);
friend Mat operator ^(Mat a,int k);
}E,A;
ULL a[MAX][MAX];
Mat operator +(Mat a,Mat b)
{
Mat c;
memset(c.mat,0,sizeof(c.mat));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
c.mat[i][j]=(a.mat[i][j]+b.mat[i][j]);
return c;
}
Mat operator *(Mat a,Mat b)
{
Mat ans;
memset(ans.mat,0,sizeof(ans.mat));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
{
ULL tmp=a.mat[i][k]*b.mat[k][j];
ans.mat[i][j]=ans.mat[i][j]+tmp;
}
return ans;
}
Mat operator ^(Mat a,int k)
{
for(int i=0;i<n;i++) for(int j=0;j<n;j++) E.mat[i][j]= (i==j);
Mat ans=E;
while(k){
if(k&1) ans=ans*a;
a=a*a,k>>=1;
}
return ans;
}
const int M = 100;
const int CD = 26;
int fail[M];
int Q[M];
int ch[M][CD];
int ID[128];
int sz;
int flag[M];
void Init()
{
fail[0]=0;
memset(ch[0],0,sizeof(ch[0]));
sz=1;
for(int i=0;i<26;i++) ID[i+'a']=i;
}
void Insert(char *s)
{
int p=0;
for(;*s;s++)
{
int c=ID[*s];
if(!ch[p][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
flag[sz]=0;
ch[p][c]=sz++;
}
p=ch[p][c];
}
flag[p]=1;
}
void Construct()
{
int *s=Q,*e=Q,v;
for(int i=0;i<CD;i++)
{
if(ch[0][i])
{
fail[ch[0][i]]=0;
*e++ = ch[0][i];
}
}
while(s!=e)
{
int u = *s++;
for(int i=0;i<CD;i++)
{
if(v=ch[u][i])
{
*e++=v;
fail[v]=ch[fail[u]][i];
flag[v]|=flag[fail[v]];
}
else
{
ch[u][i]=ch[fail[u]][i];
}
}
}
}
void init()
{
memset(A.mat,0,sizeof(A.mat));
for(int i=0;i<tn;i++)
{
for(int j=0;j<tn;j++)
{
A.mat[i][j]=a[i][j];
A.mat[i][j+tn]=a[i][j];
}
}
for(int i=tn;i<n;i++)
{
for(int j=tn;j<n;j++)
{
if(i==j)A.mat[i][j]=1;
}
}
}
int main()
{
int N;
int L;
char s[10];
while(scanf("%d%d",&N,&L)!=EOF)
{
memset(a,0,sizeof(a));
tn=1; a[0][0]=26; n=2*tn; init();
Mat ans=A^L;
ULL sum=ans.mat[0][1];
Init();
for(int i=0;i<N;i++)
{
scanf("%s",s);
Insert(s);
}
Construct();
Mat dp;
memset(dp.mat,0,sizeof(dp.mat));
for(int i=0;i<sz;i++)if(!flag[i])
{
for(int j=0;j<CD;j++) if(!flag[ch[i][j]])
{
dp.mat[i][ch[i][j]]++;
}
}
memset(a,0,sizeof(a));
for(int i=0;i<sz;i++)
{
for(int j=0;j<sz;j++)
{
a[i][j]=dp.mat[i][j];
}
}
tn=sz; n=2*tn; init();
ans=A^L;
ULL sum2=0;
for(int j=tn;j<n;j++)
{
sum2+=ans.mat[0][j];
}
printf("%I64u\n",(sum-sum2));
}
return 0;
}
#include <cstdio>
#include <cstdlib>
#include <string>
#include <climits>
#include <iostream>
#include <vector>
#include <set>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <sstream>
#include <map>
#include <cstring>
#include <queue>
using namespace std;
const int mod = 100000;
const int M = 100;
const int CD = 4;
int fail[M];
int Q[M];
int ch[M][CD];
int ID[128];
int val[M];
int sz;
void Init(){
fail[0]=0;
memset(ch[0],0,sizeof(ch[0]));
sz=1;
ID['A']=0;ID['T']=1;ID['G']=2;ID['C']=3;
}
void Insert(char *s){
int p=0;
for(;*s;s++){
int c=ID[*s];
if(!ch[p][c]){
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[p][c]=sz++;
}
p=ch[p][c];
}
val[p]=1;
}
void Construct(){
int *s=Q,*e=Q;
for(int i=0;i<CD;i++){
if(ch[0][i]){
fail[ch[0][i]] = 0;
*e++ = ch[0][i];
}
}
while(s!=e){
int u = *s++;
for(int i=0;i<CD;i++){
int &v = ch[u][i];
if(v){
*e++ = v;
fail[v]=ch[fail[u]][i];
val[v]|=val[fail[v]];
} else {
v=ch[fail[u]][i];
}
}
}
}
long long dp[100][100];
const int MAX = 100;
int n;
struct Mat {
int mat[MAX][MAX];
Mat(){
memset(mat,0,sizeof(mat));
}
void init(){
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
mat[i][j]= i==j;
}
void print(){
printf("****************\n");
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
printf(j==n-1?"%d\n":"%d ",mat[i][j]);
printf("fuckfuckfuckfuckfuck\n");
}
friend Mat operator *(Mat a,Mat b);
friend Mat operator +(Mat a,Mat b);
friend Mat operator ^(Mat a,int k);
}E;
Mat operator +(Mat a,Mat b)
{
Mat c;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
c.mat[i][j]=a.mat[i][j]+b.mat[i][j];
if(c.mat[i][j]>=mod) c.mat[i][j]-=mod;
}
return c;
}
Mat operator *(Mat a,Mat b)
{
Mat ans;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
long long tmp=0;
for(int k=0;k<n;k++)
{
tmp+=(long long)a.mat[i][k]*b.mat[k][j];
}
ans.mat[i][j]=tmp%mod;
}
return ans;
}
Mat operator ^(Mat a,int k)
{
Mat ans=E;
while(k){
if(k&1) ans=ans*a;
a=a*a,k>>=1;
}
return ans;
}
int main() {
char s[15];
int k,m;
while(scanf("%d%d",&m,&k)!=EOF) {
Init();
for(int i=0;i<m;i++) {
scanf("%s",s);
Insert(s);
}
Construct();
n=sz;
Mat ans;
for(int i=0;i<sz;i++)if(!val[i])
{
for(int j=0;j<4;j++) if(!val[ch[i][j]])
{
ans.mat[i][ch[i][j]]++;
}
}
//ans.print();
E.init();
ans=ans^k;
//ans.print();
int ret=0;
for(int i=0;i<n;i++)
{
ret+=ans.mat[0][i];
if(ret>=mod) ret-=mod;
}
printf("%d\n",ret);
}
return 0;
}