首页 技术 正文
技术 2022年11月18日
0 收藏 453 点赞 3,728 浏览 1945 个字

4569: [Scoi2016]萌萌哒

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 865  Solved: 414

Description

一个长度为n的大数,用S1S2S3…Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条件表示为四个数,l1,r1,l2,r2,即两个长度相同的区间,表示子串Sl1Sl1+1Sl1+2…Sr1与Sl2Sl2+1Sl2+2…Sr2完全相同。比如n=6时,某限制条件l1=1,r1=3,l2=4,r2=6,那么123123,351351均满足条件,但是12012,131141不满足条件,前者数的长度不为6,后者第二位与第五位不同。问满足以上所有条件的数有多少个。

Input

第一行两个数n和m,分别表示大数的长度,以及限制条件的个数。接下来m行,对于第i行,有4个数li1,ri1,li2,ri2,分别表示该限制条件对应的两个区间。1≤n≤10^5,1≤m≤10^5,1≤li1,ri1,li2,ri2≤n;并且保证ri1-li1=ri2-li2。

Output

一个数,表示满足所有条件且长度为n的大数的个数,答案可能很大,因此输出答案模10^9+7的结果即可。

Sample Input

4 2
1 2 3 4
3 3 3 3

Sample Output

90

HINT

Source

【分析】

  这题的方法还是很妙的。虽然说不是怎么新奇但是我还是没想出来嘛。。

  其实个人觉得线段树也是可以的。用线段树上的点表示区间,然后也可以merge。

  倍增也很好打啦。

  f[i][j]表示[i,i+2^j-1]这个区间,同层的区间可以merge。

  m个操作的时候就merge最多log个区间嘛。最后把merge的并查集下放到区间长度小一倍那里就好。

  要细心一点,若全都在一个并查集,答案应该是10而不是9。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Mod 1000000007
#define Maxn 100010
#define Maxd 20 int f[Maxn][Maxd],num[Maxn][Maxd],fa[Maxn*Maxd];
int son[Maxn*Maxd][]; int ffa(int x)
{
if(fa[x]!=x) fa[x]=ffa(fa[x]);
return fa[x];
} void merge(int st1,int st2,int l)
{
for(int j=;j>=;j--)
{
if((<<j)<=l)
{
int x=num[st1][j],y=num[st2][j];
if(ffa(x)!=ffa(y)) fa[ffa(x)]=y;
if((<<j)<l) merge(st1+(<<j),st2+(<<j),l-(<<j));
return;
}
}
} int main()
{
int n,m;
scanf("%d%d",&n,&m);
int cnt=;
for(int j=;(<<j)<=n;j++) for(int i=;i+(<<j)-<=n;i++)
{
num[i][j]=++cnt;
if(j!=) son[cnt][]=num[i][j-],son[cnt][]=num[i+(<<j-)][j-];
}
for(int i=;i<=cnt;i++) fa[i]=i;
for(int i=;i<=m;i++)
{
int l1,r1,l2,r2;
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
merge(l1,l2,r1-l1+);
}
for(int j=;j>;j--)
{
for(int i=;i<=n;i++) if(num[i][j])
{
if(ffa(num[i][j])!=num[i][j])
{
int x=num[i][j],y=ffa(num[i][j]);
if(ffa(son[x][])!=ffa(son[y][])) fa[ffa(son[x][])]=son[y][];
if(ffa(son[x][])!=ffa(son[y][])) fa[ffa(son[x][])]=son[y][];
}
}
}
int ans=,tot=;
for(int i=;i<=n;i++) if(ffa(num[i][])==num[i][])
{
tot++;
if(ans==) ans=1LL*ans*%Mod;
else ans=1LL*ans*%Mod;
}
if(tot==) ans=;
printf("%d\n",ans);
return ;
}

2017-04-27 15:02:37

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,086
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,561
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,410
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,183
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,820
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,903