BZOJ 4175: 小G的电话本 SAM+FFT
4175: 小G的电话本
Time Limit: 45 Sec Memory Limit: 256 MB
Submit: 195 Solved: 48
[Submit][Status][Discuss]
Description
小G是一个商人,他有一个电话本。电话本上记下了许多联系人,如timesqr、orzyhb等等。不过Tony对其中的某个联系人的名字S特别感兴趣,他从中提取出了这个联系人的名字中的所有片段,如提取出orz的 o、r、z、or、rz、orz等等。现在他想请你统计有多少个长度为k的片段对(P[1], P[2], P[3], ..., P[k]),使得在该片段对中所有片段在S中出现次数之和为他的幸运数m?注意两个片段对不同当且仅当两个片段对的某一位的片段不同,两个片段不同当且仅当这两个片段在S中的位置不同
Input
第一行两个整数k和m,意义见题目描述;第二行给出一个字符串表示Tony喜欢的联系人名字S。
Output
输出一行一个整数ans,表示答案模1005060097。
Sample Input
aaaaa
Sample Output
HINT
【样例解释】
#include<cstdio>
#include<cstring>
#define ll long long
const int len(100000),MP(1005060097),g(5),lem(262144);
struct SamNode{int nx[26],pre,right,step;}sam[len*2+10];
int top=1,root=1,now=1,last,lastson;
int cnt[len+10],p[len*2+10],b[len+10];
int n,m,k;char str[len+10];
void insert(int x)
{
last=now;now=++top;sam[now].step=sam[last].step+1;sam[now].right=1;
for(;!sam[last].nx[x]&&last;last=sam[last].pre)
sam[last].nx[x]=now;
if(!last)sam[now].pre=root;
else
{
lastson=sam[last].nx[x];
if(sam[lastson].step==sam[last].step+1)sam[now].pre=lastson;
else
{
++top;
memcpy(sam[top].nx,sam[lastson].nx,sizeof(sam[top].nx));
sam[top].pre=sam[lastson].pre;
sam[top].step=sam[last].step+1;
sam[lastson].pre=sam[now].pre=top;
for(;sam[last].nx[x]==lastson&&last;last=sam[last].pre)
sam[last].nx[x]=top;
}
}
}
void update()
{
for(int i=1;i<=top;i++)cnt[sam[i].step]++;
for(int i=1;i<=n;i++)cnt[i]+=cnt[i-1];
for(int i=top;i>=1;i--)p[cnt[sam[i].step]--]=i;
for(int i=top;i>=1;i--)
{
sam[sam[p[i]].pre].right+=sam[p[i]].right;
b[sam[p[i]].right]=(b[sam[p[i]].right]+1ll*sam[p[i]].right*(sam[p[i]].step-sam[sam[p[i]].pre].step))%MP;
}
} int R[lem+10],w[lem+10],wn,il,l,h;
void swap(int &a,int &b){if(a==b)return;a^=b;b^=a;a^=b;}
int power(int a,int b)
{
if(b<0)b=MP-1+b; long long t=1,y=a;
while(b){if(b&1)t=(t*y)%MP;y=(y*y)%MP;b>>=1;}
return (int)t;
}
struct Arr
{
void NTT(int *a,int l,int ty)
{
for(int i=0;i<l;i++)
if(i<R[i])swap(a[i],a[R[i]]);
for(int leng=2;leng<=l;leng<<=1)
{
int M=leng>>1;
wn=power(g,ty*((MP-1)/leng));
for(int i=1;i<M;i++)w[i]=(1ll*w[i-1]*wn)%MP;
for(int i=0;i<l;i+=leng)
{
for(int j=0;j<M;j++)
{
int x=a[i+j],y=(1ll*w[j]*a[i+j+M])%MP;
a[i+j]=x+y;a[i+j+M]=x-y;
a[i+j]-=a[i+j]>=MP?MP:0;
a[i+j+M]+=a[i+j+M]<0?MP:0;
}
}
}
if(ty==-1)
for(int i=0;i<l;i++)a[i]=(1ll*a[i]*il)%MP;
}
int a[lem+10];//只保留前m项
void mul(Arr &C)
{
NTT(a,l,1);
NTT(C.a,l,1);
for(int j=0;j<l;j++)a[j]=(1ll*a[j]*C.a[j])%MP;
NTT(a,l,-1);for(int j=m+1;j<l;j++)a[j]=0;
}
}X,Y,C;
void deal()
{
l=1;while(l<=m+m+1)l<<=1,h++;
for(int i=0;i<l;i++)R[i]=(R[i>>1]>>1|(i&1)<<(h-1));
il=power(l,MP-2);
}
int main()
{
// freopen("C.in","r",stdin);
// freopen("C.out","w",stdout);
scanf("%d%d",&k,&m);
scanf("%s",str);n=strlen(str);
for(int i=0;i<n;i++)insert(str[i]-'a');
update();deal();w[0]=1;
X.a[0]=1;for(int i=0;i<=m;i++)Y.a[i]=b[i];//,printf("%d\n",b[i])
for(;k;k>>=1,C=Y,Y.mul(C))
{
// printf("Y\n");
// for(int i=0;i<=m;i++)printf("%d\n",Y.a[i]);
if(k&1)C=Y,X.mul(C);
// printf("X\n");
// for(int i=0;i<=m;i++)printf("%d\n",Y.a[i]);
}
printf("%d",X.a[m]);
return 0;
}
BZOJ 4175: 小G的电话本 SAM+FFT的更多相关文章
- BZOJ 4175 小G的电话本 ——NTT
后缀自动机统计出现了各种次数的串的和. 就是所谓的生成函数 然后FFT卷积即可. 卷积快速幂$n\log n \log n$ 注意一下实现,可以少两次NTT #include <map> ...
- BZOJ4175 : 小G的电话本
用后缀树统计出出现了x次的本质不同的子串的个数,最后再乘以x,得到一个多项式. 这个多项式常数项为0,但是一次项不为0. 于是把整个多项式除以一次项,通过多项式求ln和多项式求exp求出它的幂. 最后 ...
- [BZOJ 1563] [NOI 2009] 诗人小G(决策单调性)
[BZOJ 1563] [NOI 2009] 诗人小G(决策单调性) 题面 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行中,注意一行中可以放的句子数目是没有限制的.小 G ...
- C语言实现电话本 动态开辟 信息存储于文件
下面是我用C写的一个电话本小项目,实现的功能有:添加 删除 修改 查找 排序 清空 显示,功能还是比较全的,内存也是动态开辟的.能存储于本地,能从本地读出并显示 头文件部分代码,contact.h: ...
- BZOJ 5028 小z的加油站
bzoj链接 Time limit 10000 ms Memory limit 262144 kB OS Linux 感想 树上动态gcd的第二题也好了. [x] BZOJ 2257 [JSOI200 ...
- 微信电话本可免费拨打网络电话 通话一分钟约300K流量
微信电话本新版本于昨日晚间发布,这是一款智能通讯增强软件,通话双方都下载此APP并开通免费通话功能就能使用微信电话本拨打免费网络电话,在对方无法接通情况下还能将音频转向语音信箱,微信电话本目前支持An ...
- C++之路进阶——codevs2933(诗人小G)
2933 诗人小G 2009年NOI全国竞赛 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 小G是一个出色的诗人 ...
- 苹果IPhone手机由于更新了IOS7 Beta测试版导致“激活出错”后,如何还原电话本和照片方法
苹果这狗日的,手段果然狠,因为用户提前升级了测试版又没有更新正式版,就突然把手机变砖头,既不让升级正式版,也不让备份手机中的信息,确实有必要这样吗? 我的手机是IPone4s,在看了6月Apple W ...
- Android-->发送短信页面实现(短信发送以及群发和从电话本中选择联系人)-----------》2
分析下怎么写 首先,我们需要一个输入框,可以手动的输入手机号码, 其次,很少有人愿意手动输入,那么我们需要提供一个按钮来给我们的用户选择自己电话本中的联系人(一次可以选择多个即群发) 然后,我们需要一 ...
随机推荐
- R 中数据导入
R语言数据导入 数据导入 1.保存和加载R的数据(与R.data的交互:save()函数和load()函数) a <- 1:10 save(a, file = "data/dumDa ...
- 1. docker安装
前提 系统:我这边都使用虚拟机安装的CentOS7,具体安装可以参考:Windows安装Linux虚拟机(CentOS7) yum:推荐更新下yum:yum update;我们这边CentOS7自带d ...
- clone分支,修改文件本地commit后, push回原分支失败,处理方法
从远程clone 一个仓库到本地仓库A后,由于有多个分支,经常需要切换,不同分支区别比较大,切换一下,需要重编译,于是又在本地clone了改动较大的一个分支F到仓库B: 在B仓库改动后,提交到A仓库的 ...
- SQL Server(二)——语句 转
表的创建: 1.创建列(字段):列名+类型 2.设置主键列(primary key):能够唯一标识一条数据 3.设置唯一(unique):内容不能重复 4.外键关系:一张表(从表)其中的某列引用自另外 ...
- CLR via C# 第五章学习记录(更新中)
1.设置全局溢出检查,项目属性->生成->高级->检测运算上溢/下溢 2.局部使用溢出检测 Byte b = ; b = ));// 不检测溢出 checked// 检测溢出代码段 ...
- CentOS6下用yum升级系统内核版本至最新
首先当你决定升级内核时,要想清楚为什么升级内核,因为升级内核会带来很多麻烦.所以这种事情能避免就避免 导入 Public Key rpm --import https://www.elrepo.org ...
- bzoj 2632: [neerc2011]Gcd guessing game【贪心】
这个告诉gcd的操作实际上就是告诉一个因数是否选,最坏情况是1,判断掉所有因数才能选 然后肯定是用猜不重复质数积比较划算,问题就变成若干个质数,分成数量尽量小每组乘积<=n的若干组 从大质数开始 ...
- hdu1175 连连看
连连看 HDU - 1175 “连连看”相信很多人都玩过.没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子.如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子 ...
- 洛谷P3455 [POI2007]ZAP-Queries(莫比乌斯反演)
传送门 设$$f(k)=\sum_{i=1}^{a}\sum_{j=1}^{b}[gcd(i,j)=k]$$ $$g(n)=\sum_{n|k}f(k)=\lfloor\frac{a}{n}\rflo ...
- 5G时代的智慧物流~圆通副总裁相峰
图片来自“百度百科” 本文是圆通速递CEO.国家工程实验室主任相峰先生在2019全球物流技术大会的演讲,在演讲中,相峰先生主要阐述了自己对5G的看法以及5G在物流领域的应用. 以下是演 ...