题解: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中的String不可变

    笔主前言: 众所周知,String是Java的JDK中最重要的基础类之一,在笔主心中的地位已经等同于int.boolean等基础数据类型,是超越了一般Object引用类型的高端大气上档次的存在. 但是 ...

  2. [hihocoder 1050]求树的最长链

    题目链接:http://hihocoder.com/problemset/problem/1050 两种方法: 1. 两遍dfs,第一次随便找一个根,找到距离这个根最远的点,这个点必然是最长链的一端. ...

  3. ecplise中修改reviewboard密码

    一.概述 如果想在ecplise中修改reviewboard密码,步骤请参考如下图片:

  4. jw player笔记二----修改logo

    一.修改HTML5模式下的logo 见http://blog.csdn.net/xiong_mao_1/article/details/17222757 二.修改FLASH模式下的logo IE7/8 ...

  5. 程序员的那些问题---转载自veryCD

    展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告   走过的路,回忆起来是那么曲折,把自己的一些心得体会分享给程序员兄弟姐妹们,虽然时代在变化,但是很可能你也会走我已经做过 ...

  6. 用eval转化对象

    var str = '{"name": "tom","age": 12,"sex": "man"}' ...

  7. [NOIp普及组2011]瑞士轮

    洛谷题目链接:瑞士轮 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较 ...

  8. Java并发编程--ThreadPoolExecutor

    概述 为什么要使用线程池? 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立 ...

  9. 从setting文件导包

    两种方式 from project.settings.py import s3_key 第二种: from django.conf import setting s3_key = settings.S ...

  10. SUSE LINUX 11忘记密码的解决方法

    忘记ROOT的密码 1.重新启动机器,在出现grub引导界面后,在启动linux的选项里加上init=/bin/bash,通过给内核传递init=/bin/bash参数使得OS在运行login程序之前 ...