题目传送门

题目大意

给出一个\(n\)个数的字符串,有\(m\)次查询,对于该串的子串\([l,r]\)有多少个子串满足是固定素数\(p\)的倍数。

思路

其实很简单,但是一开始想偏了。。。果然还是自己菜啊。。。

我们可以想到统计一下后缀和\(s[i]\),表示\([i,n]\)构成的数,那么,判断一个区间\([l,r]\)是不是\(p\)的倍数就等价于:

\[\dfrac{s[l]-s[r+1]}{10^{n-r}}\equiv 0 \pmod p
\]

我们发现如果\(\gcd(10,p)=1\)的话,分母就不会产生影响,于是判断条件就是:

\[s[l]\equiv s[r+1]\pmod p
\]

于是对于这种情况我们就可以用莫队\(\Theta(n\sqrt n)\)开桶记录答案。

如果\(\gcd(10,p)\not=1\)的话,那么\(p=2 \operatorname{or} 5\),我们发现这种情况对于区间\([l,r]\)判断是否的话直接判断第\(r\)位是不是\(2\operatorname{or}5\)的倍数即可。于是我们可以\(\Theta(n)\)解决这种情况。

果然还是自己菜了啊。。。这都没有看出来。。。

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define ll long long
#define MAXN 200005 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} char S[MAXN];
ll sum,ans[MAXN];int n,m,p,un,s[MAXN],tmp[MAXN],bel[MAXN],cnt[MAXN]; namespace Subtask1{
struct node{
int l,r,id;
bool operator < (const node &p)const{return bel[l] != bel[p.l] ? l < p.l : r < p.r;}
}q[MAXN];
void cge (int x,int k){sum -= 1ll * cnt[x] * (cnt[x] - 1) / 2,cnt[x] += k,sum += 1ll * cnt[x] * (cnt[x] - 1) / 2;}
void Work (){
int siz = sqrt (n);
for (Int i = n,c = 1;i;-- i,c = 1ll * c * 10 % p) s[i] = (s[i + 1] + 1ll * c * (S[i] - '0') % p) % p,bel[i] = (i - 1) / siz + 1,tmp[i] = s[i];
sort (tmp + 1,tmp + n + 2);un = unique (tmp + 1,tmp + n + 2) - tmp - 1;for (Int i = 1;i <= n + 1;++ i) s[i] = lower_bound (tmp + 1,tmp + un + 1,s[i]) - tmp;
read (m);for (Int i = 1;i <= m;++ i) read (q[i].l,q[i].r),q[i].r ++,q[i].id = i;sort (q + 1,q + m + 1);int l = 1,r = 0;
for (Int i = 1;i <= m;++ i){
while (l < q[i].l) cge (s[l ++],-1);while (l > q[i].l) cge (s[-- l],1);
while (r < q[i].r) cge (s[++ r],1);while (r > q[i].r) cge (s[r --],-1);
ans[q[i].id] = sum;
}
for (Int i = 1;i <= m;++ i) write (ans[i]),putchar ('\n');
return ;
}
} namespace Subtask2{
int snum[MAXN];ll ssum[MAXN];
void Work(){
for (Int i = 1;i <= n;++ i){
snum[i] = ((S[i] - '0') % p == 0);
ssum[i] = ssum[i - 1] + 1ll * ((S[i] - '0') % p == 0) * i;
}
read (m);
while (m --){
int l,r;read (l,r);
write (ssum[r] - ssum[l - 1] - (snum[r] - snum[l - 1]) * (l - 1)),putchar ('\n');
}
}
} signed main(){
read (p),scanf("%s",S + 1),n = strlen (S + 1);
if (p == 2 || p == 5) Subtask2::Work ();
else Subtask1::Work ();
return 0;
}

题解 [HNOI2016]大数的更多相关文章

  1. 【LG3245】[HNOI2016]大数

    [LG3245][HNOI2016]大数 题面 洛谷 题解 60pts 拿vector记一下对于以每个位置为右端点符合要求子串的左端点, 则每次对于一个询问,扫一遍右端点在vector里面二分即可, ...

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

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

  3. 4542: [Hnoi2016]大数

    4542: [Hnoi2016]大数 链接 分析: 如果p等于2或者5,可以根据最后一位直接知道是不是p的倍数,所以直接记录一个前缀和即可. 如果p不是2或者5,那么一个区间是p的倍数,当且仅当$\f ...

  4. 题解-[HNOI2016]序列

    题解-[HNOI2016]序列 [HNOI2016]序列 给定 \(n\) 和 \(m\) 以及序列 \(a\{n\}\).有 \(m\) 次询问,每次给定区间 \([l,r]\in[1,n]\),求 ...

  5. 4542: [Hnoi2016]大数

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

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

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

  7. 【bzoj4542】[Hnoi2016]大数 莫队算法

    题目描述 给出一个数字串,多次询问一段区间有多少个子区间对应的数为P的倍数.其中P为质数. 输入 第一行一个整数:P.第二行一个串:S.第三行一个整数:M.接下来M行,每行两个整数 fr,to,表示对 ...

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

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

  9. 洛谷P3245 [HNOI2016]大数 【莫队】

    题目 题解 除了\(5\)和\(2\) 后缀数字对\(P\)取模意义下,两个位置相减如果为\(0\),那么对应子串即为\(P\)的倍数 只用对区间种相同数个数\(x\)贡献\({x \choose 2 ...

随机推荐

  1. go实现堆排序

    package main import "fmt" func main(){ arr:=[]int{4,8,2,1,6,9,3,5,7,8,1,4} dui(arr) fmt.Pr ...

  2. ES6 class——getter setter音乐播放器

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. excel快捷键如下:

    ALT+ 空格键,然后按下 X ALT+ 空格键,然后按下 R  首先打开表格,在A1对角用鼠标左键单击,界面会全部选中,然后调整字体大小框里的数字,回车,表格就变大了. 同时按Alt和E,再按L   ...

  4. Leetcode 146. LRU 缓存机制

    前言 缓存是一种提高数据读取性能的技术,在计算机中cpu和主内存之间读取数据存在差异,CPU和主内存之间有CPU缓存,而且在内存和硬盘有内存缓存.当主存容量远大于CPU缓存,或磁盘容量远大于主存时,哪 ...

  5. Java的参数传递是值传递还是引用传递?

    一.前言 首先先说结论,Java中方法参数传递方式是按值传递.如果参数是基本类型,传递的是基本类型的字面量值的拷贝.如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝. 接下来深入了解一 ...

  6. docker快速创建轻量级的可移植的容器(一)

    系列其他内容 docker快速创建轻量级的可移植的容器✓ docker&flask快速构建服务接口 docker&uwsgi高性能WSGI服务器生产部署必备 docker&gu ...

  7. 发那科FANUC机器人视频学习教程

    82课时的全套发那科机器人视频教程,学完可以掌握发那科机械手的使用和编程,需要的加我微信私私聊.X241602 FANUC 是日本一家专门研究数控系统的公司,成立于1956年.是世界上最大的专业数控系 ...

  8. 斐波那契数(Java)

    斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 .该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和.也就是: F(0) = 0,F(1) = 1 F(n) = F(n ...

  9. JAVA安全基础之反射

    JAVA安全基础之反射 在JAVA安全中,反射是一个经常使用的技术,所以熟悉使用反射是非常必要的.下面就简单的讲下JAVA的反射的用法 什么是反射 每个类都有对应的Class类对象,该Class类对象 ...

  10. 论文解读《Momentum Contrast for Unsupervised Visual Representation Learning》俗称 MoCo

    论文题目:<Momentum Contrast for Unsupervised Visual Representation Learning> 论文作者: Kaiming He.Haoq ...