题目所求答案为总数减去不合法的,求不合法数与POJ 2778类似,不再赘述。
二分求等比数列的前n项和。
s(n) = a1+a2+a3+a4 +. . . . . .+an;
=(a[n/2] +1)*s(n/2)
依次递归,注意讨论n的奇偶性,矩阵亦可如此。
#include #include #include #include #include #include #include #include #include #pragma comment(linker, "/STACK:1024000000"); #define EPS (1e-8) #define LL long long #define ULL unsigned __int64 #define _LL __int64 #define INF 0x3f3f3f3f using namespace std; const int MAXN = 28; const int MAXS = 26; struct Mat { ULL mat[MAXN][MAXN]; int r,c; void Init(int val,int R,int C) { r = R,c = C; for(int i = 1; i <= r; ++i) for(int j = 1; j <= c; ++j) if(i != j) mat[i][j] = 0; else mat[i][j] = val; } }; Mat operator *(Mat a,Mat b) { Mat p; p.Init(0,a.r,b.c); for(int i = 1; i <= a.r; ++i) { for(int j = 1; j <= b.c; ++j) { for(int k = 1; k <= b.r; ++k) { p.mat[i][j] += a.mat[i][k]*b.mat[k][j]; } } } return p; } Mat operator + (Mat a,Mat b) { Mat c; c.r = a.r,c.c = a.c; for(int i = 1; i <= a.r; ++i) for(int j = 1; j <= a.c; ++j) c.mat[i][j] = a.mat[i][j] + b.mat[i][j]; return c; } Mat QuickMult(ULL k,Mat coe) { Mat p; p.Init(1,coe.r,coe.c); while(k >= 1) { if(k&1) p = p*coe; coe = coe*coe; k >>= 1; } return p; } Mat BsCalMat(ULL m,Mat p) { if(m == 1) return p; Mat tt = BsCalMat(m/2,p); Mat tmp = (QuickMult(m/2,p)*tt) + tt; if(m&1) tmp = tmp+QuickMult(m,p); return tmp; } struct N { int next[MAXS],flag,fail; }st[60]; int Top; int creat() { memset(st[Top].next,-1,sizeof(st[Top].next)); st[Top].fail = -1,st[Top].flag = 0; return Top++; } char s[12]; inline int sel(char c) { return c-'a'; } void Get_Trie(int root,char *s) { int site = 1; while(s[site] != '\0') { if(st[root].next[sel(s[site])] == -1) st[root].next[sel(s[site])] = creat(); root = st[root].next[sel(s[site])]; ++site; } st[root].flag++; } int Get_Fail(int site,int tar) { while(site != -1 && st[site].next[tar] == -1) site = st[site].fail; if(site == -1) return 0; return st[site].next[tar]; } queue q; void Get_Fail(int root) { st[root].fail = -1; q.push(root); int f; while(q.empty() == false) { f = q.front(); q.pop(); for(int i = 0; i < MAXS; ++i) { if(st[f].next[i] != -1) { st[st[f].next[i]].fail = Get_Fail(st[f].fail,i); q.push(st[f].next[i]); } } } } bool Check(int site) { if(site == -1) return true; if(st[site].flag != 0 || Check(st[site].fail) == false) return false; return true; } int Check(int site,int tar) { if(site == -1) return 0; if(st[site].next[tar] != -1) { if(st[st[site].next[tar]].flag != 0 || Check(st[site].next[tar]) == false) return -1; return st[site].next[tar]; } return Check(st[site].fail,tar); } void Cal_Mat(int root,Mat &p) { q.push(root); int f; while(q.empty() == false) { f = q.front(); q.pop(); for(int i = 0; i < MAXS; ++i) { if(st[f].next[i] != -1 && Check(st[f].next[i])) { p.mat[f+1][st[f].next[i]+1]++; q.push(st[f].next[i]); } else if(st[f].next[i] == -1) { int tmp = Check(f,i); if(tmp != -1) p.mat[f+1][tmp+1]++; } } } } ULL QuickMult(ULL x,ULL n) { if(n == 1) return x; ULL tmp = QuickMult(x,n/2); tmp = tmp*tmp; if(n&1) tmp = tmp*x; return tmp; } ULL Sum(ULL x) { if(x == 1) return 26; ULL tt = Sum(x/2); ULL tmp = QuickMult(26,x/2)*tt + tt; if(x&1) tmp = tmp + QuickMult(26,x); return tmp; } int main() { int root,i,j,n; ULL m; while(scanf("%d %I64u",&n,&m) != EOF) { Top = 0; root = creat(); for(i = 1; i <= n; ++i) { scanf("%s",s+1); Get_Trie(root,s); } Get_Fail(root); Mat t,p; p.Init(0,Top,Top); Cal_Mat(root,p); p = BsCalMat(m,p); ULL ans = 0; for(i = 1; i <= Top; ++i) ans += p.mat[1][i]; printf("%I64u\n",Sum(m)-ans); } return 0; }