• 「HNOI2016」大数


    题意

    题意

    做法

    艹,这TM和莫队有个der的关系?????????

    虽然总感觉他和莫队有关系,但是总想不到怎么做

    事实上就是莫队

    设数字为:(overline{a_1a_2a_3a_4a_5...a_n})

    (t_i)(overline{a_ia_{i+1}a_{i+2}...a_{n}}mod p)的值。

    这个(t)数组可以(O(n))求出来。

    再研究一下如果(overline{a_la_{l+1}...a_{r}})(p)的倍数呢?那么不难发现(t_{l}-t_{r+1}≡0 mod p),因为(overline{a_la_{l+1}...a_{r}}≡0mod p,{a_la_{l+1}...a_{r}}*10^{n-r}≡0mod p),所以(t_{l}≡t_{r+1})

    但是是不是(t_{l}≡t_{r+1}),那么(overline{a_la_{l+1}...a_{r}}≡0mod p),首先我们知道({a_la_{l+1}...a_{r}}*10^{n-r}≡0mod p),如果(gcd(10^{n-r},p)=1),那么这个是绝对成立的,但是如果(gcd(10^{n-r},p)≠1),则不一定成立,此时(p=2,5),那么对于这两种情况,暴力判断如果这个位置能被整除,那么以这个位置作为(r)的区间一定能被整除。

    对于(p≠2,5)的情况,就是维护([l,r+1])区间中(t)数组的相等对数,直接莫队(O(nsqrt{n}))暴力上就行了,别忘了(t)数组离散化哦。

    时间复杂度:(O(nsqrt{n}))

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define  N  110000
    using  namespace  std;
    typedef  long  long  LL;
    char  st[N];
    LL  a[N];
    LL  n,p,m;
    
    LL  f1[N];LL  f2[N];//2或者5的情况 
    
    LL  belong[N],block;//分块 
    LL  si[N],id[N],be[N],cnt;//离散化
    LL  tot[N];
    LL  ans;//移动的ans 
    struct  query
    {
    	LL  l,r,id;
    }q[N];LL  anslist[N];
    inline  bool  cmp1(LL  x,LL  y){return  si[x]<si[y];}
    inline  bool  cmp2(query  x,query  y){return  be[x.l]!=be[y.l]?x.l<y.l:x.r<y.r;}
    inline  void  add(LL  x){ans+=tot[x];tot[x]++;}
    inline  void  del(LL  x){tot[x]--;ans-=tot[x];}
    int  main()
    {
    	scanf("%lld",&p);
    	scanf("%s",st+1);n=strlen(st+1);
    	for(LL  i=1;i<=n;i++)a[i]=st[i]-'0';
    	if(p==2  ||  p==5)
    	{
    		for(LL  i=1;i<=n;i++)
    		{
    			if(a[i]%p==0)f1[i]++,f2[i]+=i;
    			f1[i]+=f1[i-1],f2[i]+=f2[i-1];
    		}
    		scanf("%lld",&m);
    		for(LL  i=1;i<=m;i++)
    		{
    			LL  l,r;scanf("%lld%lld",&l,&r);
    			LL  x1=f1[r]-f1[l-1];LL  x2=f2[r]-f2[l-1];
    			printf("%lld
    ",x2-(LL)x1*(l-1));
    		}
    	}
    	else
    	{
    		LL  mo=1;
    		for(LL  i=n;i>=1;i--)si[i]=(si[i+1]+mo*a[i])%p,mo=(mo*10)%p,id[i]=i;
    		si[++n]=0;id[n]=n;
    		sort(id+1,id+n+1,cmp1);
    		for(LL  i=1;i<=n;i++)
    		{
    			if(i==1  ||  be[cnt]!=si[id[i]])cnt++,be[cnt]=si[id[i]];
    			si[id[i]]=cnt;
    		}
    		
    		block=sqrt(n);
    		for(LL  i=1;i<=n;i++)be[i]=(i-1)/block+1;
    		
    		scanf("%lld",&m);
    		for(LL  i=1;i<=m;i++){scanf("%lld%lld",&q[i].l,&q[i].r);q[i].id=i;}
    		sort(q+1,q+m+1,cmp2);
    		
    		LL  l=1,r=0;
    		for(LL  i=1;i<=m;i++)
    		{
    			q[i].r++;
    			while(r<q[i].r)add(si[r+1]),r++;
    			while(l>q[i].l)add(si[l-1]),l--;
    			while(r>q[i].r)del(si[r]),r--;
    			while(l<q[i].l)del(si[l]),l++;
    			anslist[q[i].id]=ans;
    		}
    		for(LL  i=1;i<=m;i++)printf("%lld
    ",anslist[i]);
    	}
    	return  0;
    }
    
  • 相关阅读:
    javaweb一
    javaweb三、JDBC访问数据库
    Java学习笔记十
    socket qt基础版本
    QT+VS+添加console 解决方案
    QT创建TCP Socket通信
    左值引用与右值引用
    STL 中 map和set的区别
    C++中STL哈希表介绍
    虚函数总结
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/13914840.html
Copyright © 2020-2023  润新知