【莫队】bzoj4542: [Hnoi2016]大数
挺有意思的,可以仔细体味一下的题;看白了就是莫队板子。
Description
小 B 有一个很大的数 S,长度达到了 N 位;这个数可以看成是一个串,它可能有前导 0,例如00009312345
。小B还有一个素数P。现在,小 B 提出了 M 个询问,每个询问求 S 的一个子串中有多少子串是 P 的倍数(0 也
是P 的倍数)。例如 S为0077时,其子串 007有6个子串:0,0,7,00,07,007;显然0077的子串007有6个子串都是素
数7的倍数。
Input
第一行一个整数:P。第二行一个串:S。第三行一个整数:M。接下来M行,每行两个整数 fr,to,表示对S 的
子串S[fr…to]的一次询问。注意:S的最左端的数字的位置序号为 1;例如S为213567,则S[1]为 2,S[1…3]为 2
13。N,M<=100000,P为素数
Output
输出M行,每行一个整数,第 i行是第 i个询问的答案。
题目分析
一个区间[l,r]产生贡献即$number_{i,j}\equiv 0\ ({\rm mod}\ p)$.
按照常见套路来说,应该把区间拆成关于端点的式子。用$pre[i]$表示前$i$位在十进制下的数值,那么即$number_{i,j}=pre[j]-10^{j-i+1}*pre[i-1]$。将式子移项发现左右两边形如$f(r)=f(l-1)$(据说这是一种经典的莫队套路)那么于此已经将区间问题转化为关于单点的可$O(1)$修改的子问题了。
之后的操作就相对套路:将$n+1$个$f(i)$(不要忘记统计$f(0)$)预先离散化处理;然后常规莫队操作。
注意莫队要先修改再更新!
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
const int maxn = ; int blk[maxn];
struct QRs
{
int l,r,id;
bool operator < (QRs a) const
{
if (blk[l]==blk[a.l]) return r < a.r;
return blk[l] < blk[a.l];
}
}q[maxn];
char s[maxn];
int p,n,m,cnt,tot,size,inv10;
int lbd,rbd,lSd[maxn],rSd[maxn];
int ans[maxn],sum[maxn],pre[maxn],t[maxn]; int read()
{
char ch = getchar();
int num = ;
bool fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = ;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
if (fl) num = -num;
return num;
}
int qmi(int a, int b)
{
int ret = ;
while (b)
{
if (b&) ret = 1ll*ret*a%p;
b >>= , a = 1ll*a*a%p;
}
return ret;
}
void lAdd(int lbd)
{
rSd[sum[lbd]]++, tot+=rSd[sum[lbd-]], lSd[sum[lbd-]]++;
}
void rAdd(int rbd)
{
lSd[sum[rbd-]]++, tot+=lSd[sum[rbd]], rSd[sum[rbd]]++;
}
void lErase(int lbd)
{
lSd[sum[lbd-]]--, tot-=rSd[sum[lbd-]], rSd[sum[lbd]]--;
}
void rErase(int rbd)
{
rSd[sum[rbd]]--, tot-=lSd[sum[rbd]], lSd[sum[rbd-]]--;
}
int main()
{
freopen("bignum.in","r",stdin);
freopen("bignum.out","w",stdout);
p = read(), scanf("%s",s+);
n = strlen(s+), size = sqrt(n+0.5)+;
if (p==||p==){
for (int i=; i<=n; i++)
{
ans[i] = ans[i-], sum[i] = sum[i-];
if ((s[i]-'')%p==) ans[i]++, sum[i] += i;
}
m = read();
for (int i=; i<=m; i++)
{
int l = read(), r = read();
printf("%d\n",sum[r]-sum[l-]-(ans[r]-ans[l-])*(l-));
}
return ;
}
for (int i=; i<=n; i++) blk[i] = i/size, pre[i] = (pre[i-]*10ll%p+s[i]-'')%p;
inv10 = qmi(, p-);
for (int i=, pr=; i<=n; i++)
t[i] = sum[i] = 1ll*pre[i]*pr%p, pr = 1ll*pr*inv10%p;
std::sort(t, t+n+), cnt = std::unique(t, t+n+)-t-;
for (int i=; i<=n; i++)
sum[i] = std::lower_bound(t, t+cnt+, sum[i])-t+;
m = read();
for (int i=; i<=m; i++) q[i].l = read(), q[i].r = read(), q[i].id = i;
std::sort(q+, q+m+);
lbd = , rbd = ;
for (int i=; i<=m; i++)
{
while (lbd < q[i].l) lErase(lbd++);
while (lbd > q[i].l) lAdd(--lbd);
while (rbd > q[i].r) rErase(rbd--);
while (rbd < q[i].r) rAdd(++rbd);
ans[q[i].id] = tot;
}
for (int i=; i<=m; i++) printf("%d\n",ans[i]);
return ;
}
END
【莫队】bzoj4542: [Hnoi2016]大数的更多相关文章
- [BZOJ4542] [Hnoi2016] 大数 (莫队)
Description 小 B 有一个很大的数 S,长度达到了 N 位:这个数可以看成是一个串,它可能有前导 0,例如00009312345.小B还有一个素数P.现在,小 B 提出了 M 个询问,每个 ...
- bzoj4542 [Hnoi2016]大数 莫队+同余
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4542 题解 我们令 \(f_i\) 表示从 \(i\) 到 \(n\) 位组成的数 \(\bm ...
- BZOJ4542: [Hnoi2016]大数
Description 小 B 有一个很大的数 S,长度达到了 N 位:这个数可以看成是一个串,它可能有前导 0,例如00009312345.小B还有一个素数P.现在,小 B 提出了 M 个询问,每个 ...
- bzoj4542: [Hnoi2016]大数(莫队)
这题...离散化...$N$和$n$搞错了...查了$2h$...QAQ 考虑$s[l...r]$,可以由两个后缀$suf[l]-suf[r+1]$得到$s[l...r]$代表的数乘$10^k$得到的 ...
- 【BZOJ4542】[Hnoi2016]大数 莫队
[BZOJ4542][Hnoi2016]大数 Description 小 B 有一个很大的数 S,长度达到了 N 位:这个数可以看成是一个串,它可能有前导 0,例如00009312345.小B还有一个 ...
- 【bzoj4542】[Hnoi2016]大数 莫队算法
题目描述 给出一个数字串,多次询问一段区间有多少个子区间对应的数为P的倍数.其中P为质数. 输入 第一行一个整数:P.第二行一个串:S.第三行一个整数:M.接下来M行,每行两个整数 fr,to,表示对 ...
- BZOJ.4542.[HNOI2016]大数(莫队)
题目链接 大数除法是很麻烦的,考虑能不能将其条件化简 一段区间[l,r]|p,即num[l,r]|p,类似前缀,记后缀suf[i]表示[i,n]的这段区间代表的数字 于是有 suf[l]-suf[r+ ...
- 【bzoj5452】[Hnoi2016]大数(莫队)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4542 首先若p=2,5则这题就是道傻逼题,前缀和搞一下没了.如果p为其他质数,那么可以 ...
- 洛谷P3245 [HNOI2016]大数(莫队)
题意 题目链接 Sol 莫队板子题.. 维护出每个位置开始的字符串\(mod P\)的结果,记为\(S_i\) 两个位置\(l, r\)满足条件当且仅当\(S_l - S_r = 0\),也就是\(S ...
随机推荐
- 微信小程序实战
为了积攒粉丝,公司决定做一个一分钱姓名测算的小程序引导大家关注公众号. 实现的需求就是 1 首页 用户编辑姓名和性别进行提交 2 测算结果页 实现分享和支付功能 3 测算历史页面 看到用户曾经测算记 ...
- [Android]HttpClient和HttpURLConnection的区别
转载:http://blog.csdn.net/guolin_blog/article/details/12452307 最近在研究Volley框架的源码,发现它在HTTP请求的使用上比较有意思,在A ...
- Educational Codeforces Round 65 (Rated for Div. 2) A. Telephone Number
链接:https://codeforces.com/contest/1167/problem/A 题意: A telephone number is a sequence of exactly 11 ...
- 2019湘潭校赛 G(并查集)
要点 题目传送 题目本质是每个点必属于两个集合中的一个,伴随的性质是:如果一个人说别人true,则他们一定属于同一阵营:如果说别人fake,一定不属于同一阵营. 每个点拆为\(i\)和\(i + n\ ...
- hdu2027 trie树 字典树模板
#include <iostream> #include <cstdio> #include <cstring> #include <sstream> ...
- ORA-06502 when awr report produce
最近在生成一套系统的AWR报告时出现了如下报错:ORA-06502: PL/SQL: numeric or value error: character string buffer too small ...
- javac 找不到文件 的可能原因
初学Java还不太明白,竟在些简单的事情上栽跟头,分享一下省的麻烦. 当我们配置好JDK和环境变量之后,在命令行下输入javac,说明我们的安装是正确的.
- C#字符串变量使用
string由于是引用类型,所以,声明的字符串变量会存储到堆上,而且该变量是不可变的,一旦初始化了该变量,该内存区域中存储的内容将不能更改.在对字符串操作时,是在堆上创建了一个新的字符串变量,并将新的 ...
- ubuntu 14.04 安装minidwep-gtk
一,安装相关的依赖 sudo apt-get install build-essential libssl-dev iw libpcap-dev sqlite3 libsqlite3-dev libp ...
- Spring Cloud--搭建Eureka注册中心服务
使用RestTemplate远程调用服务的弊端: Eureka注册中心: Eureka原理: 搭建Eureka服务 引pom 启动类: 启动类上要加上@EnableEurekaServer注解: 配置 ...