[BZOJ4542]大数
2016-04-19 21:07
357 查看
如何判断一个炒鸡大的数$n$能不能被另一个数$P$整除,,,我们有如下结论若$xmodP=a$,且$(n*10^{k}+x)modP=a$,$k$为$x$的长度,$gcd(P,10^{k})=1$那么$nmodP=0$
胡乱证明分割线**********
因为$(n*10^{k}+x)modP=((n*10^{k})modP+xmodP)modP=a$,且$xmodP=a$,则$(n*10^{k})modP=0$
当且仅当$10^{k}modP$不为$0$时$nmodP=0$
当满足这个条件时,我们把$x$看作序列的后缀$P$,问题就转化为求区间$[l,r+1]$中,有多少对$a$相同,,,莫队again
由于$P$是质数,,,所以需要特判的只有$2$和$5$
所谓的特判就是数一哈有几个偶数,几个$0$或$5$什么的,,,
爸在嚄见新机表
View Code
胡乱证明分割线**********
因为$(n*10^{k}+x)modP=((n*10^{k})modP+xmodP)modP=a$,且$xmodP=a$,则$(n*10^{k})modP=0$
当且仅当$10^{k}modP$不为$0$时$nmodP=0$
当满足这个条件时,我们把$x$看作序列的后缀$P$,问题就转化为求区间$[l,r+1]$中,有多少对$a$相同,,,莫队again
由于$P$是质数,,,所以需要特判的只有$2$和$5$
所谓的特判就是数一哈有几个偶数,几个$0$或$5$什么的,,,
爸在嚄见新机表
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define maxn 100005 struct node{ int l,r,blc,id; ll ans; }q[maxn]; char s[maxn]; int n,m,hh,cnt[maxn]; ll P,tong[maxn],A[maxn],hsh[maxn],pre[maxn]; bool cmp1(node a,node b){ if(a.blc!=b.blc)return a.blc<b.blc; else if(a.r!=b.r)return a.r<b.r; else return a.l<b.l; } bool cmp2(node a,node b){ return a.id<b.id; } void PP(){ s[++n]='0'; ll mi=1; for(int i=n;i;i--){ hsh[++hh]=A[i]=((s[i]-'0')*mi%P+A[i+1]%P)%P; mi=mi*10%P; } sort(hsh+1,hsh+1+hh); hh=unique(hsh+1,hsh+1+hh)-(hsh+1); for(int i=1;i<=n;i++) A[i]=lower_bound(hsh+1,hsh+1+hh,A[i])-hsh; } void MD(){ sort(q+1,q+1+m,cmp1); int l=1,r=0; ll ans=0; for(int i=1;i<=m;i++){ while(r<q[i].r)ans+=tong[A[++r]]++; while(r>q[i].r)ans-=--tong[A[r--]]; while(l>q[i].l)ans+=tong[A[--l]]++; while(l<q[i].l)ans-=--tong[A[l++]]; q[i].ans=ans; } sort(q+1,q+1+m,cmp2); for(int i=1;i<=m;i++) printf("%lld\n",q[i].ans); } void solve1(){ PP(); int block=sqrt(n); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].r++,q[i].id=i; q[i].blc=(q[i].l-1)/block+1; } MD(); } void solve2(){ for(int i=1;i<=n;i++){ pre[i]=pre[i-1]; cnt[i]=cnt[i-1]; if((P==2&&(s[i]-'0')%2==0)||(P==5&&(s[i]-'0'==0||s[i]-'0'==5))) pre[i]+=i,cnt[i]++; } scanf("%d",&m); int l,r; for(int i=1;i<=m;i++){ scanf("%d%d",&l,&r); printf("%lld\n",pre[r]-pre[l-1]-(cnt[r]-cnt[l-1])*(l-1)); } } int main(){ scanf("%lld%s",&P,s+1); n=strlen(s+1); if(P!=2&&P!=5)solve1(); else solve2(); return 0; }
View Code
相关文章推荐
- Volatile关键字详解
- 动态的添加和丢弃关键点---32
- 水平居中
- 模板的特化
- Android TV开发--实现屏保图片云端可配置
- Android开发中,那些让你相见恨晚的方法、类或接口
- ZOJ Problem Set - 3490 String Successor(字符串模拟)
- java.sql.SQLException: 无效的列索引
- 平衡二叉树(AVL树)的基本操作
- 常规选择器——进阶选择器
- ubantu下解压命令大全
- 三和韓長庚 著 易學原理總論 對讀 101_120
- Python风格规范
- Matlab 的fspecial函数用法
- leetcode——81——Search in Rotated Sorted Array II
- 机器学习总结1_学习理论
- Oracle-SQL02
- Android资源文件分类
- 使用Mybatis-Generator自动生成Dao、Model、Mapping相关文件
- POJ 2406:Power Strings