题目描述

给出一个数字串,多次询问一段区间有多少个子区间对应的数为P的倍数。其中P为质数。

输入

第一行一个整数:P。第二行一个串:S。第三行一个整数:M。接下来M行,每行两个整数 fr,to,表示对S 的子串S[fr…to]的一次询问。注意:S的最左端的数字的位置序号为 1;例如S为213567,则S[1]为 2,S[1…3]为 213。

N,M<=100000,P为素数

输出

输出M行,每行一个整数,第 i行是第 i个询问的答案。

样例输入

11
121121
3
1 6
1 5
1 4

样例输出

5
3
2


题解

莫队算法

设 $b[i]=S[i...n]\ \text{mod}\ p$ ,那么 $S[l,r]$ 为 $p$ 的倍数,当且仅当: $\frac{b[l]-b[r+1]}{10^{r-l}}\ \text{mod}\ p=0$ 。

当 $p=2$ 或 $p=5$ 时,直接通过数字串末位判断是不是 $p$ 的倍数。设 $v[i]=[i\ \text{mod}\ p=0]$ ,维护 $v[i]$ 和 $v[i]·i$ 的前缀和即可快速得出答案。

当 $p\neq 2$ 且 $p\neq 5$ 时,$p$ 与 $10$ 互质。此时条件简化为:$b[l]\equiv b[r+1]\ (\text{mod}\ p)$ 。

因此原问题转化为:求 $[l,r+1]$ 内 $b$ 值相等的数对的数目。

将 $b$ 离散化,使用莫队算法,用桶维护离散化后的某个 $b$ 的出现次数,指针移动时统计答案即可。

时间复杂度 $O(n\sqrt n)$

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
typedef long long ll;
ll p;
char str[N];
namespace task1
{
ll s1[N] , s2[N];
void solve()
{
int n , m , i , l , r;
scanf("%s%d" , str + 1 , &m) , n = strlen(str + 1);
for(i = 1 ; i <= n ; i ++ )
{
s1[i] = s1[i - 1] , s2[i] = s2[i - 1];
if((str[i] - '0') % p == 0) s1[i] ++ , s2[i] += i;
}
while(m -- )
{
scanf("%d%d" , &l , &r);
printf("%lld\n" , s2[r] - s2[l - 1] - (l - 1) * (s1[r] - s1[l - 1]));
}
}
}
namespace task2
{
struct data
{
int l , r , bl , id;
bool operator<(const data &a)const {return bl == a.bl ? r < a.r : bl < a.bl;}
}q[N];
int a[N] , mp[N];
ll b[N] , v[N] , ans[N];
void solve()
{
int n , m , i , si , lp = 1 , rp = 0;
ll t = 1 , now = 0;
scanf("%s%d" , str + 1 , &m) , n = strlen(str + 1) , si = (int)sqrt(n);
for(i = n ; i ; i -- , t = t * 10 % p) v[i] = b[i] = (b[i + 1] + (str[i] - '0') * t) % p;
v[n + 1] = 0 , sort(v + 1 , v + n + 2);
for(i = 1 ; i <= n + 1 ; i ++ ) a[i] = lower_bound(v + 1 , v + n + 2 , b[i]) - v;
for(i = 1 ; i <= m ; i ++ ) scanf("%d%d" , &q[i].l , &q[i].r) , q[i].r ++ , q[i].bl = (q[i].l - 1) / si , q[i].id = i;
sort(q + 1 , q + m + 1);
for(i = 1 ; i <= m ; i ++ )
{
while(lp > q[i].l) now += mp[a[--lp]] , mp[a[lp]] ++ ;
while(rp < q[i].r) now += mp[a[++rp]] , mp[a[rp]] ++ ;
while(lp < q[i].l) mp[a[lp]] -- , now -= mp[a[lp++]];
while(rp > q[i].r) mp[a[rp]] -- , now -= mp[a[rp--]];
ans[q[i].id] = now;
}
for(i = 1 ; i <= m ; i ++ ) printf("%lld\n" , ans[i]);
}
}
int main()
{
scanf("%lld" , &p);
if(p == 2 || p == 5) task1::solve();
else task2::solve();
return 0;
}

【bzoj4542】[Hnoi2016]大数 莫队算法的更多相关文章

  1. [BZOJ4542] [Hnoi2016] 大数 (莫队)

    Description 小 B 有一个很大的数 S,长度达到了 N 位:这个数可以看成是一个串,它可能有前导 0,例如00009312345.小B还有一个素数P.现在,小 B 提出了 M 个询问,每个 ...

  2. bzoj4542 [Hnoi2016]大数 莫队+同余

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4542 题解 我们令 \(f_i\) 表示从 \(i\) 到 \(n\) 位组成的数 \(\bm ...

  3. 【BZOJ4542】[Hnoi2016]大数 莫队

    [BZOJ4542][Hnoi2016]大数 Description 小 B 有一个很大的数 S,长度达到了 N 位:这个数可以看成是一个串,它可能有前导 0,例如00009312345.小B还有一个 ...

  4. BZOJ.4542.[HNOI2016]大数(莫队)

    题目链接 大数除法是很麻烦的,考虑能不能将其条件化简 一段区间[l,r]|p,即num[l,r]|p,类似前缀,记后缀suf[i]表示[i,n]的这段区间代表的数字 于是有 suf[l]-suf[r+ ...

  5. 【BZOJ4540】[Hnoi2016]序列 莫队算法+单调栈

    [BZOJ4540][Hnoi2016]序列 Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,a ...

  6. [bzoj4540][Hnoi2016][序列] (莫队算法+单调栈+st表)

    Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-1,ar.若1≤l≤s≤t≤r≤n,则称a ...

  7. 洛谷P3245 [HNOI2016]大数(莫队)

    题意 题目链接 Sol 莫队板子题.. 维护出每个位置开始的字符串\(mod P\)的结果,记为\(S_i\) 两个位置\(l, r\)满足条件当且仅当\(S_l - S_r = 0\),也就是\(S ...

  8. [BZOJ4542] [JZYZOJ2014][Hnoi2016] 大数(莫队+离散化)

    正经题解在最下面 http://blog.csdn.net/qq_32739495/article/details/51286548 写的时候看了大神的题解[就是上面那个网址],看到下面这段话 观察题 ...

  9. bzoj 4542: [Hnoi2016]大数 (莫队)

    Description 小 B 有一个很大的数 S,长度达到了 N 位:这个数可以看成是一个串,它可能有前导 0,例如00009312345.小B还有一个素数P.现在,小 B 提出了 M 个询问,每个 ...

随机推荐

  1. yaml中的锚点和引用

    项目引入yaml语言来写配置文件,最近发现利用其锚点&和引用*的功能,可以极大减少配置文件中的重复内容,将相同配置内容收敛到锚点处,修改时,只需要修改锚点处的内容,即可在所有引用处生效. ya ...

  2. tkinter事件高级用法实例

    from tkinter import * import threading, time trace = 0 class CanvasEventsDemo: def __init__(self, pa ...

  3. 减少Java垃圾的产生,降低内存使用量

    1.尽量少使用静态的变量,因为它会一直占用内存, 2.尽量少使用String字符串去做拼接,相加.因为String是定长的每次相加都会产生新的临时对象,生成垃圾对象,尽量使用StringBuffer, ...

  4. [ Continuously Update ] This is an *Index Page*.

    The links below present papers in certain fields. Despite overlaps exist, their emphasis is markedly ...

  5. SST:Single-Stream Temporal Action Proposals论文笔记

    SST:Single-Stream Temporal Action Proposals 这是本仙女认认真真读完且把算法全部读懂(其实也不是非常懂)的第一篇论文 CVPR2017 一作 论文写作的动机m ...

  6. python基础-02-while格式化逻辑运算

    python其他知识目录 1.循环打印“我是小马过河” while True:    print('我是小马过河') #4.用while从一打印到10 #5.请通过循环,1 2 3 4 5 6 8 9 ...

  7. phpquery 学习笔记

    phpQuery是一个基于PHP的服务端开源项目,它可以让PHP开发人员轻松处理DOM文档内容,比如获取某新闻网站的头条信息.更有意思的是,它采用了jQuery的思想,你可以像使用jQuery一样处理 ...

  8. Scrum立会报告+燃尽图(Beta阶段第二周第六次)

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2414 项目地址:https://coding.net/u/wuyy694 ...

  9. Android:有关下拉菜单导航的学习(供自己参考)

    Android:有关==下拉菜单导航==的学习 因为先前的学习都没想着记录自己的学习历程,所以该博客才那么迟才开始写. 内容: ==下拉菜单导航== 学习网站:android Spinner控件详解 ...

  10. 网页调用vlc并播放网络视频

    环境:windows/android/ios windows端保存以下内容为reg文件并运行 Windows Registry Editor Version 5.00 [HKEY_CLASSES_RO ...