[BZOJ4542]大数

如何判断一个炒鸡大的数$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$什么的,,,

爸在嚄见新机表

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define maxn 100005
 5 struct node{ int l,r,blc,id; ll ans; }q[maxn];
 6 char s[maxn];
 7 int n,m,hh,cnt[maxn];
 8 ll P,tong[maxn],A[maxn],hsh[maxn],pre[maxn];
 9 bool cmp1(node a,node b){
10     if(a.blc!=b.blc)return a.blc<b.blc;
11     else if(a.r!=b.r)return a.r<b.r;
12     else return a.l<b.l;
13 }
14 bool cmp2(node a,node b){ return a.id<b.id; }
15 void PP(){
16     s[++n]='0';
17     ll mi=1;
18     for(int i=n;i;i--){
19         hsh[++hh]=A[i]=((s[i]-'0')*mi%P+A[i+1]%P)%P;
20         mi=mi*10%P;
21     }
22     sort(hsh+1,hsh+1+hh);
23     hh=unique(hsh+1,hsh+1+hh)-(hsh+1);
24     for(int i=1;i<=n;i++)
25         A[i]=lower_bound(hsh+1,hsh+1+hh,A[i])-hsh;
26 }
27 void MD(){
28     sort(q+1,q+1+m,cmp1);
29     int l=1,r=0; 
30     ll ans=0;
31     for(int i=1;i<=m;i++){
32         while(r<q[i].r)ans+=tong[A[++r]]++;
33         while(r>q[i].r)ans-=--tong[A[r--]];
34         while(l>q[i].l)ans+=tong[A[--l]]++;
35         while(l<q[i].l)ans-=--tong[A[l++]];
36         q[i].ans=ans;
37     }
38     sort(q+1,q+1+m,cmp2);
39     for(int i=1;i<=m;i++)
40         printf("%lld\n",q[i].ans);
41 }
42 void solve1(){
43     PP();
44     int block=sqrt(n);
45     scanf("%d",&m);
46     for(int i=1;i<=m;i++){
47         scanf("%d%d",&q[i].l,&q[i].r);
48         q[i].r++,q[i].id=i;
49         q[i].blc=(q[i].l-1)/block+1;
50     }
51     MD();
52 }
53 void solve2(){
54     for(int i=1;i<=n;i++){
55         pre[i]=pre[i-1];
56         cnt[i]=cnt[i-1];
57         if((P==2&&(s[i]-'0')%2==0)||(P==5&&(s[i]-'0'==0||s[i]-'0'==5)))
58             pre[i]+=i,cnt[i]++;
59     }
60     scanf("%d",&m);
61     int l,r;
62     for(int i=1;i<=m;i++){
63         scanf("%d%d",&l,&r);
64         printf("%lld\n",pre[r]-pre[l-1]-(cnt[r]-cnt[l-1])*(l-1));
65     }
66 }
67 int main(){
68     scanf("%lld%s",&P,s+1);
69     n=strlen(s+1);
70     if(P!=2&&P!=5)solve1();
71     else solve2();
72     return 0;
73 }
View Code

 

posted @ 2016-04-19 21:07  Ngshily  阅读(554)  评论(0编辑  收藏  举报