AFO

[SCOI2016]萌萌哒

Description

一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条

件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串Sl1Sl1+1Sl1+2...Sr1与Sl2Sl2+1Sl2+2...S

r2完全相同。比如n=6时,某限制条件l1=1,r1=3,l2=4,r2=6,那么123123,351351均满足条件,但是12012,13

1141不满足条件,前者数的长度不为6,后者第二位与第五位不同。问满足以上所有条件的数有多少个。

在倍增数组上并查集!

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define LL long long 
using namespace std;
const int P = 1e9+7;
const int M = 200001;
int n,m,k,a[M],f[22][M],l1,l2,r1,r2,res=1;

int ff(int x,int y)
{
	if(f[y][x]==x) return x; 
	
	return f[y][x]=ff(f[y][x],y);}

void link(int x,int y,int len)
{
	if(ff(x,len) !=ff(y,len)) f[len][f[len][x]]=f[len][y];
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)	for(int j=0;j<=20;j++) f[j][i]=i;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
		for(int j=20;j>=0;j--) if((1<<j)<=r1-l1+1) link(l1,l2,j), l1+=1<<j, l2+=1<<j;
	}
	for(int j=20;j;j--)
		for(int i=1;i+(1<<j)-1<=n;i++)
			link(i,ff(i,j),j-1), link(i+(1<<j-1),ff(i,j)+(1<<j-1),j-1);
	for(int i=1;i<=n;i++) if(f[0][i]==i) res=(LL)res*10%P;
	res=(LL)res*300000003ll%P;
	printf("%d",res);
}
posted @ 2019-09-09 14:56  ZUTTER☮  阅读(95)  评论(0)    收藏  举报