zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    ExtJS小技巧
    Oracle 表的行数、表占用空间大小,列的非空行数、列占用空间大小 查询
    NPM 私服
    IDEA 不编译java以外的文件
    SQL 引号中的问号在PrepareStatement 中不被看作是占位符
    Chrome 浏览器自动填表呈现淡黄色解决
    批量删除Maven 仓库未下载成功.lastupdate 的文件
    Oracle 11g 监听很慢,由于监听日志文件太大引起的问题(Windows 下)
    Hibernate 自动更新表出错 建表或添加列,提示标识符无效
    Hibernate 自动更新表出错 More than one table found in namespace
  • 原文地址:https://www.cnblogs.com/asuldb/p/10375554.html
Copyright © 2011-2022 走看看