Description

Solution

考虑用倍增来处理答案:

设 \(f[i][j]\) 表示长度恰好为 \(2^{i}\) 的哈希值为 \(j\) 的字符串的种数

\(dp[i][j]\) 表示长度小于等于 \(2^{i}\) 的哈希值为 \(j\) 的字符串的种数

容易得到转移式子:

\(f[i+1][j*base^{2^{i}}+k]=\sum f[i][j]*f[i][k]\)

\(dp[i+1][j*base^{2^{i}}+k]=dp[i][j*base^{2^{i}}+k]+\sum f[i][j]*dp[i][k]\)

发现两个转移是一个卷积的形式,\(NTT\) 优化转移即可

最后就是得到长度 \(<=n\) 的答案

可以像 \(dp\) 数组的求法一样,直接倍增求出即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=200005,mod=998244353;
inline int qm(int x,int k){
int sum=1;
while(k){
if(k&1)sum=1ll*sum*x%mod;
x=1ll*x*x%mod;k>>=1;
}
return sum;
}
int L,R[N],inv,n,P,D,len,st[N],top=0,ans[N];ll b[N];
inline void init(){
for(n=1;n<=(P<<1);n<<=1)L++;
for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
inv=qm(n,mod-2);
}
inline void NTT(int *A,int o){
for(int i=0;i<n;i++)if(i<R[i])swap(A[i],A[R[i]]);
for(int i=1;i<n;i<<=1){
int t0=qm(3,(mod-1)/(i<<1)),x,y;
for(int j=0;j<n;j+=(i<<1)){
int t=1;
for(int k=0;k<i;k++,t=1ll*t0*t%mod){
x=A[j+k];y=1ll*A[i+j+k]*t%mod;
A[j+k]=(x+y)%mod;A[j+k+i]=(x-y+mod)%mod;
}
}
}
if(o==-1)reverse(A+1,A+n);
}
inline void mul(int *A,int *B){
NTT(A,1);NTT(B,1);
for(int i=0;i<=n;i++)A[i]=1ll*A[i]*B[i]%mod;
NTT(A,-1);
}
int f[20][N],dp[20][N],A[N],B[N];
inline void Modify(int i){
for(int j=0;j<n;j++)A[j]=B[j]=0;
for(int j=0;j<P;j++)A[j*b[i]%P]=(A[j*b[i]%P]+ans[j])%mod;
for(int j=0;j<P;j++)B[j]=(B[j]+f[i][j])%mod;
mul(A,B);
for(int j=0;j<P;j++)ans[j]=dp[i][j];
for(int j=0;j<n;j++)ans[j%P]=(ans[j%P]+1ll*A[j]*inv)%mod;
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>len>>b[0]>>P>>D;
init();
for(int i='a';i<='z';i++)dp[0][i%P]++,f[0][i%P]++;
for(int i=0;(1<<(i+1))<=len;i++){
b[i+1]=b[i]*b[i]%P;
for(int j=0;j<n;j++)A[j]=B[j]=0;
for(int j=0;j<P;j++)A[j*b[i]%P]=(A[j*b[i]%P]+f[i][j])%mod;
for(int j=0;j<P;j++)B[j]=(B[j]+f[i][j])%mod;
mul(A,B);
for(int j=0;j<n;j++)f[i+1][j%P]=(f[i+1][j%P]+1ll*A[j]*inv)%mod; for(int j=0;j<n;j++)A[j]=B[j]=0;
for(int j=0;j<P;j++)A[j*b[i]%P]=(A[j*b[i]%P]+dp[i][j])%mod;
for(int j=0;j<P;j++)B[j]=(B[j]+f[i][j])%mod;
mul(A,B);
for(int j=0;j<n;j++)dp[i+1][j%P]=(dp[i+1][j%P]+1ll*A[j]*inv)%mod;
for(int j=0;j<P;j++)dp[i+1][j]=(dp[i+1][j]+dp[i][j])%mod;
}
for(int i=20;i>=0;i--)
if((1<<i)<=len)len-=(1<<i),st[++top]=i;
for(int i=0;i<P;i++)ans[i]=dp[st[top]][i];
while(--top)Modify(st[top]);
printf("%d\n",ans[D]);
return 0;
}

51nod 1752 哈希统计的更多相关文章

  1. 51nod 1779逆序对统计(状压DP)

    按照插入数的大小排序, 然后依次进行dp. 用一个状态表示n个数是否被选了 10110 就是表示第1.3.4个位置都选了 那么如果此时这个数该填到5这个位置,那么必定会造成一个逆序(因为下一个数会填到 ...

  2. 51Nod 快速傅里叶变换题集选刷

    打开51Nod全部问题页面,在右边题目分类中找到快速傅里叶变换,然后按分值排序,就是本文的题目顺序. 1.大数乘法问题 这个……板子就算了吧. 2.美妙的序列问题 长度为n的排列,且满足从中间任意位置 ...

  3. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

  4. LeetCode 350: 两个数组的交集 II Intersection of Two Arrays II

    题目: 给定两个数组,编写一个函数来计算它们的交集. Given two arrays, write a function to compute their intersection. 示例 1: 输 ...

  5. LeetCode:137. 只出现一次的数字 II

    LeetCode:137. 只出现一次的数字 II 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. ...

  6. 用Hash Table(哈希散列表)实现统计文本每个单词重复次数(频率)

    哈希表在查找方面有非常大应用价值,本文记录一下利用哈希散列表来统计文本文件中每个单词出现的重复次数,这个需求当然用NLP技术也很容易实现. 一.基本介绍 1.Hash Key值:将每个单词按照字母组成 ...

  7. 51Nod 1282 时钟 —— 最小表示法 + 字符串哈希

    题目链接:https://vjudge.net/problem/51Nod-1282 1282 时钟 题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难 ...

  8. 51nod 1267:4个数和为0 哈希

    1267 4个数和为0 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题  收藏  关注 给出N个整数,你来判断一下是否能够选出4个数,他们的和为0,可以则输出&qu ...

  9. 51Nod 算法马拉松28 B题 相似子串 哈希

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - 51Nod1753 题意概括 两个字符串相似定义为: 1.两个字符串长度相等 2.两个字符串对应位置上有且仅有 ...

随机推荐

  1. C语言博客作业--数组

    一.PTA实验作业 题目1.求整数序列中出现次数最多的数 1.本题PTA提交列表 2.设计思路 定义整形变量n,max,count分别表示整数个数,出现次数最大值,出现次数.定义循环变量i,j. 输入 ...

  2. 2017-2018-1 Java演绎法 第八周 作业

    团队任务:UML设计 团队组长:袁逸灏 本次编辑:刘伟康 团队分工 第一次使用泳道图,感觉非常方便,从图中的箭头和各个活动框中可以清晰地看出分工流程: 不过既然是博客园,分工就不能只贴图,markdo ...

  3. 2017-2018-1 1623 bug终结者 冲刺001

    bug终结者 冲刺001 冲刺阶段任务分配 任务 工作量比例 完成时间 负责人 第一篇博客:各个成员的任务安排 1/7 12月1日 20162322 朱娅霖 第二篇博客:欢迎界面,主菜单界面 1/7 ...

  4. Android Studio使用过程中遇到的错误

    > 错误1 1. This fragment should provide a default constructor (a public constructor wit 代码不规范,这个错误是 ...

  5. 关于GPUImage的导入

    对于GPUImage的使用方面,GitHub上已经非常详细了,就不一一赘述了,但是对于项目的导入来说,最好的方式是 1.下载GPUImage并解压 2.打开压缩包后如图 3.打开终端,cd到此目录 4 ...

  6. LoadRunner录制手机APP教程

    1.     开启fiddler 2.     打开HP Virtual User Generator,新建->Web (HTTP/HTML)>创建 3.     点击开始录制: (1) ...

  7. Vim 中文社区:期待你的加入

    我们的愿景 Vim 中文社区一直比较零散,缺少凝聚力,现有的一些群经常也是水的可以的,讨论各种无关紧要的内容,于是导致很大一部分人,将这些群丢入了群助手,渐渐地他们也淡出了 vim 中文社区. 而我理 ...

  8. Tcl与Design Compiler (一)——前言

    已经学习DC的使用有一段时间了,在学习期间,参考了一些书,写了一些总结.我也不把总结藏着掖着了,记录在博客园里面,一方面是记录自己的学习记录,另一方面是分享给大家,希望大家能够得到帮助.参考的书籍有很 ...

  9. jsp 九大内置对象和其作用详解

    JSP中一共预先定义了9个这样的对象,分别为:request.response.session.application.out.pagecontext.config.page.exception 1. ...

  10. python CSS

    CSS 一. css的四种引入方式   1.行内式  2.嵌入式  3. 链接式 将一个.css文件引入到HTML文件中 1 <link href="mystyle.css" ...