「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}}≡0\mod p,{a_la_{l+1}...a_{r}}*10^{n-r}≡0\mod p\),所以\(t_{l}≡t_{r+1}\)

但是是不是\(t_{l}≡t_{r+1}\),那么\(\overline{a_la_{l+1}...a_{r}}≡0\mod p\),首先我们知道\({a_la_{l+1}...a_{r}}*10^{n-r}≡0\mod 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(n\sqrt{n})\)暴力上就行了,别忘了\(t\)数组离散化哦。

时间复杂度:\(O(n\sqrt{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\n",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\n",anslist[i]);
	}
	return  0;
}
posted @ 2020-11-02 15:51  敌敌畏58  阅读(60)  评论(0编辑  收藏  举报