题目描述

给出一个数字串,多次询问一段区间有多少个子区间对应的数为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. 20155321 《Java程序设计》实验报告一:Java开发环境的熟悉(Windows+IDEA)

    实验要求 使用JDK编译.运行简单的Java程序: 使用IDEA 编辑.编译.运行.调试Java程序. 实验内容 命令行下Java程序开发 打开windows下的cmd → 输入cd Code命令进入 ...

  2. Wiki版产品需求---产品需求文档到底是谁的?产品到底是谁的?

    在听了测试的一通唠叨之后,"内部实现一堆逻辑,只有一句话的需求文档","文档那么简单,我们怎么测试啊",心中突然想起来自己曾经干的一件当时觉得还不错的事情,但是 ...

  3. 【原创】Odoo开发文档学习之:ORM API接口(ORM API)(边Google翻译边学习)

    官方ORM API开发文档:https://www.odoo.com/documentation/10.0/reference/orm.html Recordsets(记录集) New in vers ...

  4. codevs 5429 多重背包

    5429 多重背包 http://codevs.cn/problem/5429 分析: f[i]=g[j-k*siz[i]]+k*val[i]; 发现一个状态d只会更新,d+siz[i],d+2*si ...

  5. Mybaits: MyBaits的xml文件中大于号和小于号的转义

    < 小于号  <     > 大于号  & & 和 & ' 单引号 &apos; " 双引号  "

  6. Training: MySQL I (MySQL, Exploit, Training)

    题目链接:http://www.wechall.net/challenge/training/mysql/auth_bypass1/index.php?highlight=christmas 的确是非 ...

  7. 9.14 DP合集水表

    9.14 DP合集水表 关键子工程 在大型工程的施工前,我们把整个工程划分为若干个子工程,并把这些子工程编号为 1. 2. --. N:这样划分之后,子工程之间就会有一些依赖关系,即一些子工程必须在某 ...

  8. 洛谷1552 [APIO2012]派遣

    洛谷1552 [APIO2012]派遣 原题链接 题解 luogu上被刷到了省选/NOI- ...不至于吧 这题似乎有很多办法乱搞? 对于一个点,如果他当管理者,那选的肯定是他子树中薪水最少的k个,而 ...

  9. ubuntu的学习教程(常用操作)

    摘要 最近在学习linux,把自己学习过程中遇到的常用操作以及一些有助于理解的内容记录下来.我主要用的是ubuntu系统 命令提示符 '~' 这个是指用户的家目录,用户分为root用户和普通用户,ro ...

  10. 基于ejabberd实现各个客户端消息同步

    先上图再说(左侧是web端,右侧是ios端)              要实现上面的功能,如果所有设备都在线的话,那么carboncopy(xmpp xep-0280协议)这个模块是可以实现接收到的消 ...