【bzoj4542】大数 莫队

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=4542

【题解】

把n个后缀组成的数字全部对p取模。

若s[l] ~ s[n]的余数和s[r] ~ s[n]的余数相同,那么s[l] ~ s[r - 1]区间内的数字就是p的倍数(l < r)

证明:设k为s[r-1]%p,x=r-l,n为s[l] ~ s[r - 1]区间内的数字,k%p=a

则(k+n*10^x)%p=a,若gcd(10^x,p)=1,因为k%p=a,所以n%p=0

由上面的证明过程可以知道当p=2或5时不成立,我们需要特判一下:

当p=2或5时,用b[i]记录在i及左边满足(s[i]-'0')%p=0的数的个数,c[i]记录i及左边的答案。

那么对于询问[l,r]的答案就是(c[r]-c[l-1])-(b[r]-b[l-1])*(l-1),这个动手推一下就出来了。

然后回到p不是2或5的情况:

很显然,这是一个经典的问题:在[l,r+1]内有多少对相同的数。

另外,注意离散化的使用。

/*************
  bzoj 4542
  by chty
  2016.11.17
*************/
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
#define FILE "read"
#define MAXN 100010
#define up(i,j,n) for(ll i=j;i<=n;i++)
#define down(i,j,n) for(ll i=j;i>=n;i--)
struct node{ll x,y,id;}q[MAXN];
ll p,n,m,now,block,ans[MAXN],a[MAXN],num[MAXN],b[MAXN],c[MAXN];
char ch[MAXN];
mapMap;
namespace Init{
	char buf[1<<15],*fs,*ft;
	inline char getc() {return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
	inline ll read(){
		ll x=0,f=1;  char ch=getchar();
		while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
		while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
		return x*f;
	}
}
namespace Mo_Team{
	ll cnt[MAXN];
	bool cmp(node a,node b) {return a.x/block==b.x/block?a.yl)  del(a[l++]);
			while(q[i].xr)  add(a[++r]);
			while(q[i].y


你可能感兴趣的:(bzoj,莫队)