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. 实验三《Java面向对象程序设计》实验报告

    20162308 实验三<Java面向对象程序设计>实验报告 实验内容 XP基础 XP核心实践 IDEA工具学习 密码学算法基础 实验步骤 (一)Refactor/Reformat使用 p ...

  2. alpha-咸鱼冲刺day2-紫仪

    总汇链接 一,合照 emmmmm.自然是没有的. 二,项目燃尽图 三,项目进展 今天并没有什么进展,弄了好久好像也只研究出怎么把JS的功能块插入进去.html的信息提交这些还不知道要怎么弄. 四,问题 ...

  3. SQL函数返回表的示例-Z

    create function [dbo].[GetOperateCustGroup] ( ), ) ) returns @TempTable table (MaxPrice float,MinPri ...

  4. 项目Alpha冲刺Day6

    一.会议照片 二.项目进展 1.今日安排 熟悉后台框架并编写.继续搭建前台框架模版.熟悉前端框架开发流程.完成前端热部署配置.完成部分后台用户信息相关接口.解决后台jdk1.8日期在框架中的使用. 2 ...

  5. 20145237 《Java程序设计》第三周学习总结

    20145237 <Java程序设计>第3周学习总结 教材学习内容总结 第四章主要讲了Java基本类型中的类类型,如何定义类.构造函数.使用标准类.基本类型打包器.数组复制.字符串等内容查 ...

  6. Django 个性化管理员站点

    from django.contrib import admin # Register your models here. from .models import Moment class Momen ...

  7. Flask-uploads 简单使用

    pip install flask-uploads#先导入次此处需要用到的库: from flask_uploads import UploadSet, IMAGES, configure_uploa ...

  8. github感悟

    刚学GitHub进入网页全英文的,感觉很惊讶,自己竟然要在全英文的网站上学习,虽然是英文的但并不感觉有压力,可能之前用eclipse就是全英文的现在除了惊讶,没太多的想法.然后就是我的GitHub地址 ...

  9. Linux进程管理:查杀进程

    一.查看进程 Linux下显示系统进程的命令ps,最常用的有ps -ef 和ps aux.这两个到底有什么区别呢? 两者没太大差别,讨论这个问题,要追溯到Unix系统中的两种风格,System V风格 ...

  10. LINGO 基础学习笔记

    LINGO 中建立的优化模型可以由5个部分组成,或称为 5 段(section): (1)集合段(SETS):这部分要以"SETS:"开始,以"ENDSETS" ...