• 【BZOJ】4542: [Hnoi2016]大数


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4542


    给定一个由数字构成的字符串${S_{1,2,3,...,n}}$,一个正素数$P$,每次询问给定一对$l$,$r$求:

    $${sum_{l=1}^{n}sum_{r=i}^{n}left [ sum _{i=l}^{r}S[i]*10^{r-i} \,\,\,\,MOD\,\,\,\,P=0 ight ]}$$


      即以位置$x$开头的后缀的数字$%P$之后的值为$val[x]$,如果一个数字对应区间${[l,r]}$它$%p$为$0$的充要条件为${val[l]=val[r-1]}$,然后套上莫队算法,离散化$val$数组,就变成了经典的查询一个区间相同数字的点对有多少个。

      注意:$p=2,5$的情况中并不满足以上性质,记一下前缀和然后特判即可。


      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<cstdlib>
      6 #include<cmath>
      7 #include<cstring>
      8 using namespace std;
      9 #define maxn 300100
     10 #define llg long long
     11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
     12 llg n,m,p,quan[maxn],tail,val[maxn],len,se[maxn],KUAI;
     13 long long ans,Ans[maxn],jisuan1[maxn],jisuan2[maxn];
     14 char s[maxn];
     15 struct Q_
     16 {
     17     llg l,r,num;
     18 }ask[maxn];
     19 
     20 bool cmp(const Q_&a,const Q_&b) {if (a.l/KUAI==b.l/KUAI) return a.r<b.r; else return a.l/KUAI<b.l/KUAI; }
     21 
     22 llg find(llg x)
     23 {
     24     llg l=1,r=len,wz=-1,mid;
     25     while (l<=r)
     26     {
     27         mid=(l+r)>>1;
     28         if (quan[mid]<=x) {wz=mid; l=mid+1;}else {r=mid-1;} 
     29     }
     30     return wz;
     31 }
     32 
     33 void solve()
     34 {
     35     cin>>m;
     36     for(int i=1;i<=n;i++)
     37     { 
     38         jisuan1[i]=jisuan1[i-1]; jisuan2[i]=jisuan2[i-1];
     39         if( (s[i]-'0')%p==0 )
     40              {
     41             jisuan1[i]++;
     42             jisuan2[i]+=i;
     43              }
     44    
     45     }
     46     for(int i=1;i<=m;i++)
     47     {
     48         llg x,y;
     49         scanf("%lld%lld",&x,&y);
     50         printf("%lld
    ",jisuan2[y]-jisuan2[x-1] - (x-1)*(jisuan1[y]-jisuan1[x-1]));
     51     }
     52 }
     53 
     54 void init()
     55 {
     56     cin>>p;
     57     scanf("%s",s+1);
     58     n=strlen(s+1);
     59     KUAI=sqrt(n)+1;
     60     if (p==5 || p==2) return ;
     61     cin>>m;
     62     for (llg i=1;i<=m;i++) scanf("%lld%lld",&ask[i].l,&ask[i].r),ask[i].r++,ask[i].num=i;
     63     sort(ask+1,ask+m+1,cmp);
     64     llg C=1;
     65     tail=1;quan[1]=0; 
     66     for (llg i=n;i>=1;i--)
     67     {
     68         val[i]=val[i+1]+C*(s[i]-'0');
     69         val[i]%=p;
     70         quan[++tail]=val[i];
     71         C*=10; C%=p;
     72     }
     73     sort(quan+1,quan+tail+1);
     74     len=unique(quan+1,quan+tail+1)-(quan+1);
     75     for (llg i=1;i<=n+1;i++) val[i]=find(val[i]); 
     76 }
     77 
     78 int main()
     79 {
     80     yyj("number");
     81     init();
     82     if (p==2 || p==5) {solve(); return 0;}
     83 
     84     llg l=ask[1].l,r=ask[1].r;
     85     for (llg i=l;i<=r;i++)
     86     {
     87         ans+=se[val[i]];
     88         se[val[i]]++;
     89     }
     90     Ans[ask[1].num]=ans;
     91     for (llg k=2;k<=m;k++)
     92     {
     93         llg nl=ask[k].l,nr=ask[k].r;
     94         if (nr>r)
     95         {
     96             for (llg i=r+1;i<=nr;i++)
     97             {
     98                 ans+=se[val[i]];
     99                 se[val[i]]++;
    100             }
    101         }
    102         if (nr<r)
    103         {
    104             for (llg i=r;i>nr;i--)
    105             {
    106                 ans-=se[val[i]]-1;
    107                 se[val[i]]--;
    108             }
    109         }
    110         if (l<nl)
    111         {
    112             for (llg i=l;i<nl;i++)
    113             {
    114                 ans-=se[val[i]]-1;
    115                 se[val[i]]--;
    116             }
    117         }
    118         if (l>nl)
    119         {
    120             for (llg i=l-1;i>=nl;i--)
    121             {
    122                 ans+=se[val[i]];
    123                 se[val[i]]++;
    124             }
    125         }
    126         Ans[ask[k].num]=ans;
    127         l=nl,r=nr;
    128     }
    129     for (llg i=1;i<=m;i++) printf("%lld
    ",Ans[i]); 
    130     return 0;
    131 }
    本文作者:xrdog 作者博客:http://www.cnblogs.com/Dragon-Light/ 转载请注明出处,侵权必究,保留最终解释权!
  • 相关阅读:
    Linux Systemcall By INT 0x80、Llinux Kernel Debug Based On Sourcecode
    ELF(Executable and Linkable Format)
    Linux文件权限;ACL;Setuid、Setgid、Stick bit特殊权限;sudo提权
    Linux System Calls Hooking Method Summary
    GCC、Makefile编程学习
    Linux Process/Thread Creation、Linux Process Principle、sys_fork、sys_execve、glibc fork/execve api sourcecode
    Linux中断技术、门描述符、IDT(中断描述符表)、异常控制技术总结归类
    浅议SNMP安全、SNMP协议、网络管理学习
    DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录
    RIP、OSPF、BGP、动态路由选路协议、自治域AS
  • 原文地址:https://www.cnblogs.com/Dragon-Light/p/6399252.html
Copyright © 2020-2023  润新知