题解:http://blog.csdn.net/xingyeyongheng/article/details/10005923

这里采用了二分法求等比数列前n项和。

等比数列前n项和也可以用矩乘快速幂来求[a 1]    [Sn]    =    [Sn+1]

                    [0 1]    [a  ]          [   a   ]

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
typedef unsigned long long ull;
typedef vector<ull> vec;
typedef vector<vec> mat;
typedef pair<mat,mat> Point2;
typedef pair<ull,ull> Point;
int N;
mat I;
mat operator * (const mat &a,const mat &b)
{
mat c(N,vec(N));
for(int i=0;i<N;++i)
for(int j=0;j<N;++j)
for(int k=0;k<N;++k)
c[i][j]=c[i][j]+a[i][k]*b[k][j];
return c;
}
mat operator - (const mat &a,const mat &b)
{
mat c(N,vec(N));
for(int i=0;i<N;++i)
for(int j=0;j<N;++j)
c[i][j]=a[i][j]-b[i][j];
return c;
}
mat operator + (const mat &a,const mat &b)
{
mat c(N,vec(N));
for(int i=0;i<N;++i)
for(int j=0;j<N;++j)
c[i][j]=a[i][j]+b[i][j];
return c;
}
Point sum_a_n(ull a,ull n)
{
if(n==0)
return Point(1,1);
Point t=sum_a_n(a,n>>1);
if(n&1)
return Point(t.first*t.first*a,t.second*(t.first*a+1));
else
return Point(t.first*t.first,(t.second-t.first)*(t.first*a+1)+t.first);
}
Point2 sum_A_n(mat a,ull n)
{
if(n==0)
return Point2(I,I);
Point2 t=sum_A_n(a,n>>1);
if(n&1)
return Point2(t.first*t.first*a,t.second*(t.first*a+I));
else
return Point2(t.first*t.first,(t.second-t.first)*(t.first*a+I)+t.first);
}
queue<int>q;
int child[40][26],fail[40],size=1;
bool word[40];
void Insert(char S[])
{
int len=strlen(S);
int now=0;
for(int i=0;i<len;++i)
{
if(!child[now][S[i]-'a'])
child[now][S[i]-'a']=size++;
now=child[now][S[i]-'a'];
}
word[now]=1;
}
void build()
{
fail[0]=-1;
q.push(0);
while(!q.empty())
{
int U=q.front(); q.pop();
for(int i=0;i<26;++i)
if(child[U][i])
{
int V=fail[U];
while(V!=-1)
{
if(child[V][i])
{
fail[child[U][i]]=child[V][i];
break;
}
V=fail[V];
}
if(V==-1)
fail[child[U][i]]=0;
if(word[fail[child[U][i]]])
word[child[U][i]]=1;
q.push(child[U][i]);
}
else if(U)
child[U][i]=child[fail[U]][i];
}
}
int n,ma2[40];
ull m;
void Init()
{
memset(child,0,sizeof(child));
memset(fail,0,sizeof(fail));
memset(word,0,sizeof(word));
N=0;
size=1;
}
int main()
{
//freopen("hdu2243.in","r",stdin);
char s[8];
while(cin>>n>>m){
Init();
for(int i=1;i<=n;++i)
{
scanf("%s",s);
Insert(s);
}
build();
for(int i=0;i<size;++i)
if(!word[i])
ma2[i]=N++;
I.assign(N,vec(N));
for(int i=0;i<N;++i)
I[i][i]=1;
mat A(N,vec(N));
for(int i=0;i<size;++i)
for(int j=0;j<26;++j) if((!word[i]) && (!word[child[i][j]]))
++A[ma2[i]][ma2[child[i][j]]];
A=sum_A_n(A,m).second-I;
ull ans=sum_a_n(26,m).second-1;
for(int i=0;i<N;++i)
ans=ans-A[0][i];
cout<<ans<<endl;
}
return 0;
}

【AC自动机】【矩阵乘法】【等比数列】hdu2243 考研路茫茫——单词情结的更多相关文章

  1. HDU2243 考研路茫茫——单词情结 ——AC自动机、矩阵优化

    题目链接:https://vjudge.net/problem/HDU-2243 考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memor ...

  2. hdu2243 考研路茫茫——单词情结【AC自动机】【矩阵快速幂】

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. HDU2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)

    与POJ2778一样.这题是求长度不超过n且包含至少一个词根的单词总数. 长度不超过n的单词总数记为Sn,长度不超过n不包含词根的单词总数记为Tn. 答案就是,Sn-Tn. Sn=26+262+263 ...

  4. [hdu2243]考研路茫茫——单词情结(AC自动机+矩阵快速幂)

    题意:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个. 解题关键:利用补集转化的思想,先求一个词根也不包含的单词个数,然后用总的减去即可.长度不超过L需要用矩阵维数增加一倍 ...

  5. hdu2243考研路茫茫——单词情结(ac+二分矩阵)

    链接 跟2778差不多,解决了那道题这道也不成问题如果做过基本的矩阵问题. 数比较大,需要用unsigned longlong 就不需要mod了 溢出就相当于取余 #include <iostr ...

  6. HDU-2243 考研路茫茫——单词情结(AC自动机)

    题目大意:给n个单词,长度不超过L的单词有多少个包含n个单词中的至少一个单词. 题目分析:用长度不超过L的单词书目减去长度在L之内所有不包含任何一个单词的书目. 代码如下: # include< ...

  7. hdu2243考研路茫茫——单词情结

    Problem Description 背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如&q ...

  8. HDU2243 考研路茫茫――单词情结

    Description 背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab&q ...

  9. HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

随机推荐

  1. Java super和this

    this this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针. this的用法在java中大体可以分为3种: 1.普通的直接引用 这种就不用讲了,this相当于是指向当前对象本 ...

  2. C++ 智能指针的简单实现

    智能指针的用处:在c++中,使用普通指针容易造成堆内存的泄露问题,即程序员会忘记释放,以及二次释放,程序发生异常时内存泄漏等问题,而使用智能指针可以更好的管理堆内存.注意,在这里智能指针是一个类而非真 ...

  3. Ubuntu下hadoop集群搭建

    --修改IP地址(克隆镜像后可修改可不修改) http://jingyan.baidu.com/article/e5c39bf5bbe0e739d7603396.html -------------- ...

  4. 「6月雅礼集训 2017 Day2」A

    [题目大意] 给出一棵树,求有多少对点(u,v)满足其路径上不存在两个点a,b满足(a,b)=1 n<=10^5 [题解] 考虑找出所有不符合的点对,共有n*ln(n)对,他们要么是祖先-> ...

  5. 【洛谷 P2346】四子连棋(状态压缩,搜索)

    其实这题可以直接二进制状压做,1表示黑棋,0表示白棋,另外记录下2个空点的位置就行了. 具体看代码(冗长): #include <iostream> #include <cstdio ...

  6. 基于x64的处理器意思

    基于x64的处理器意思是CPU的架构是X64的,也是64位的CPU. 基本简介: "x86-64",有时会简称为"x64",是64位微处理器架构及其相应指令集的 ...

  7. UVALIVE 2686 Stargates

    尼玛真深坑合时p[x] = y 就RE,p[y] = x 就AC . #include <map> #include <set> #include <list> # ...

  8. Linux内核学习之中断 中断本质【转】

    转自:http://www.linuxidc.com/Linux/2011-11/47657.htm [中断概述] 中断本质上是一种特殊的电信号,由硬件设备发向处理器.异常和中断的不同是异常在产生时必 ...

  9. git放弃本地commit,未push

    如果不小心commit了一个不应该commit的修改,但是还没有push,想撤销那个commit. 步骤: a) git log:获取commit id: b) git reset --hard co ...

  10. 安装并解决purcell/emacs.d网络问题

    安装: $ git clone https://github.com/purcell/emacs.d.git ~/.emacs.d 不使用https访问lisp库: $ sed -i 's/https ...