zoukankan      html  css  js  c++  java
  • [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
    ",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
    ",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
  • 相关阅读:
    公司系统缓慢-分析数据库CPU过高原因-连接数
    克隆虚拟机的相关设置
    centos7基本设置和优化
    遇到的问题和解决集中
    chrome优化调教
    shell三剑客之小弟grep
    迭代器和生成器
    函数进阶
    函数介绍&参数的使用
    文件处理中光标的移动以及文件的修改
  • 原文地址:https://www.cnblogs.com/Ngshily/p/5409409.html
Copyright © 2011-2022 走看看