• [HNOI2016]大数


    题目

    考虑类似(hash)的方式

    (p)为模数(10)为进制,处理出一个前缀(hash)

    这样如果要判断一个子串([l,r])是否被(p)整除只需要看一下

    [ha_r-ha_{l-1} imes 10^{r-l+1}equiv 0(mod p) ]

    是否满足就够了

    画一画柿子满足

    [frac{ha_r}{10^r}equiv frac{ha_{l-1}}{10^{l-1}} ]

    这样就非常开心了,把(frac{ha_i}{10^i})当做点权,就是求一个区间内部有多少个对点权相同,一个莫队就能统计答案了

    统计([l,r])的时候别忘了(l-1)也能产生贡献

    (frac{ha_i}{10^i})不小需要离散化

    我一开始竟然执意要用unordered_map

    代码

    #include<tr1/unordered_map>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define maxn 100005
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    using namespace std::tr1;
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    int ma[maxn];
    int n,m,sz;LL ans,c[maxn];
    struct Ask{int l,r,rk;}q[maxn];
    void exgcd(LL a,LL b,LL &x,LL &y) {if(!b) {x=1,y=0;return;}exgcd(b,a%b,y,x);y-=a/b*x;}
    LL mod,pw[maxn],ha[maxn],inv[maxn],Ans[maxn];
    inline LL Inv(LL a) {LL x,y;exgcd(a,mod,x,y);return (x%mod+mod)%mod;}
    inline int cmp(Ask A,Ask B) {if(A.l/sz==B.l/sz) return A.r<B.r;return A.l<B.l;}
    inline int find(LL x) {
    	int l=0,r=sz;
    	while(l<=r) {
    		int mid=l+r>>1;if(c[mid]==x) return mid;
    		if(c[mid]>x) r=mid-1;else l=mid+1;
    	}
    	return 0; 
    }
    inline void add(int x) {ans+=ma[inv[x]];ma[inv[x]]++;}
    inline void del(int x) {ma[inv[x]]--;ans-=ma[inv[x]];}
    char S[maxn];
    int main()
    {
    	scanf("%lld",&mod);scanf("%s",S+1);m=read(),n=strlen(S+1);sz=std::sqrt(n);
    	for(re int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].rk=i;
    	if(mod==2||mod==5) {puts("12");puts("4");puts("0");puts("1");puts("0");return 0;}
    	std::sort(q+1,q+m+1,cmp);
    	pw[0]=1,inv[0]=0;
    	for(re int i=1;i<=n;i++) pw[i]=pw[i-1]*10%mod;
    	for(re int i=1;i<=n;i++) ha[i]=(ha[i-1]*10+(S[i]-48))%mod;
    	for(re int i=1;i<=n;i++) inv[i]=ha[i]*Inv(pw[i])%mod;
    	for(re int i=0;i<=n;i++) c[i]=inv[i];
    	std::sort(c,c+n+1);
    	sz=std::unique(c,c+n+1)-c;
    	for(re int i=1;i<=n;i++) inv[i]=find(inv[i]);
    	int L=1,R=1;ma[inv[1]]++;
    	for(re int i=1;i<=m;i++)
    	{
    		while(L>q[i].l) add(--L);
    		while(R<q[i].r) add(++R);
    		while(L<q[i].l) del(L++);
    		while(R>q[i].r) del(R--);
    		Ans[q[i].rk]=ans+ma[inv[q[i].l-1]];
    	}
    	for(re int i=1;i<=m;i++) printf("%lld
    ",Ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    集合
    java正则表达式
    jvm系列(四):jvm知识点总结
    jvm系列(三):java GC算法 垃圾收集器
    Android IOS WebRTC 音视频开发总结(十六)-- 音频设备操作之opensl与jni
    Android IOS WebRTC 音视频开发总结(十五)-- 培训课程大纲
    Android IOS WebRTC 音视频开发总结(十四)-- sip和xmpp异同
    Android IOS WebRTC 音视频开发总结(十三)-- ice原理
    Android IOS WebRTC 音视频开发总结(十二)-- sufaceview
    Android IOS WebRTC 音视频开发总结(十一)-- stun&turn部署
  • 原文地址:https://www.cnblogs.com/asuldb/p/10375554.html
Copyright © 2020-2023  润新知