题目描述

一个长度为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,后者第二位与第五位不同。问满足以上所有条件的数有多少个。

输入输出格式

输入格式:

第一行两个数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。

输出格式:

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

题意:

给出长度为n,并且有m个限制l1,r1,l2,r2,指区间l1-r1和l2-r2的数完全相同,求最后数的可能性;

题解:
①笨拙的我首先考虑暴力算法,枚举i = l1 to l2,然后把l1-r1和l2-r2的元素一一合并(并查集),但是太慢了。。。。。。。。

②太慢加速就好了,引入倍增并查集:
考虑f[x][y]为第x层,第一个位置为y,f[x][y]代表的x层区间y,y+(1<<x)-1的合并情况,每次我们把l1-r1区间长度二进制拆分后与l2-r2的对应拆分区间在正确的x上合并,统计答案的时候,如果f[x][y]和另一个标号为
fa的区间合并了,那么就让x-1层的y和fa合并,y+(1<<x-1)和fa+(1<<x-1)合并;

 #include<cstdio>
#include<iostream>
using namespace std;
const int N = ,mod = 1e9+;
int n,m,f[N][],p[];
char gc(){
static char *p1,*p2,s[];
if(p1==p2) p2=(p1=s)+fread(s,,,stdin);
return(p1==p2)?EOF:*p1++;
}
int rd(){
int x = ; char c = gc();
while(c<''||c>'') c = gc();
while(c>=''&&c<='') x=x*+c-'',c=gc();
return x;
}
int find(int j,int k){
return(f[j][k]==j)?j:f[j][k]=find(f[j][k],k);
}
void Union(int l1,int l2,int k){
if(find(l1,k) != find(l2,k))
f[f[l1][k]][k] = f[l2][k];
}
int main()
{ freopen("bzoj4569.in","r",stdin);
freopen("bzoj4569.out","w",stdout);
n=rd();m=rd();
for(int i= p[] = ;i <= ;i++) p[i] = p[i-]<<;
for(int i = ;i <= ;i++)
for(int j = ;j <= n;j++){
if(j+p[i]->n) break;
f[j][i] = j;
}
for(int i = ,l1,l2,r1,r2,len;i <= m;i++){
l1=rd(),r1=rd(),l2=rd(),r2=rd();
for(int k = ;k >= ;k--) if(l1+p[k]-<=r1) {
Union(l1,l2,k);
l1=l1+p[k],l2=l2+p[k];
}
}
for(int i = ;i >= ;i--)
for(int j = ;j+p[i]-<=n;j++){
if(find(j,i)!=j)
{
Union(j,f[j][i],i-);
Union(j+p[i-],f[j][i]+p[i-],i-);
}
}
int tot = ,ans=,tmp = ;
for(int i = ;i <= n;i++)
if(find(i,)==i) tot++;
tot--;while(tot){if(tot&) ans=1ll*ans*tmp%mod; tot>>=; tmp = 1ll*tmp*tmp%mod;}
printf("%d\n",ans);
return ;
}//by tkys_Austin;

【bzoj4569 scoi2016】萌萌哒的更多相关文章

  1. BZOJ4569 SCOI2016萌萌哒(倍增+并查集)

    一个显然的暴力是用并查集记录哪些位之间是相等的.但是这样需要连nm条边,而实际上至多只有n条边是有用的,冗余过多. 于是考虑优化.使用类似st表的东西,f[i][j]表示i~i+2^j-1与f[i][ ...

  2. [BZOJ4569][SCOI2016]萌萌哒(倍增+并查集)

    首先有一个显然的$O(n^2)$暴力做法,将每个位置看成点,然后将所有限制相等的数之间用并查集合并,最后答案就是9*(10^连通块的个数).(特判n=1时就是10). 然后比较容易想到的是,由于每次合 ...

  3. BZOJ4569 [SCOI2016]萌萌哒 【并查集 + 倍增】

    题目链接 BZOJ4569 题解 倍增的思想很棒 题目实际上就是每次让我们合并两个区间对应位置的数,最后的答案\(ans = 9 \times 10^{tot - 1}\),\(tot\)是联通块数, ...

  4. BZOJ4569 : [Scoi2016]萌萌哒

    建立ST表,每层维护一个并查集. 每个信息可以拆成两条长度为$2$的幂次的区间相等的信息,等价于ST表里两对点的合并. 然后递归合并,一旦发现已经合并过了就退出. 因为一共只会发生$O(n\log n ...

  5. 2018.07.31 bzoj4569: [Scoi2016]萌萌哒(并查集+倍增)

    传送门 对于每个限制,使用倍增的二进制拆分思想,用并查集数组fa[i][j]" role="presentation" style="position: rel ...

  6. bzoj4569: [Scoi2016]萌萌哒(ST表+并查集)

    好喵喵的题 将一个要求用ST表分割成logn个要求,如果把f[i][j]和f[u][v]在同一个集合,那么f[i][j-1]和f[u][v-1],f[i+2^(j-1)][j-1]和f[u][u+2^ ...

  7. [bzoj4569][SCOI2016]萌萌哒-并查集+倍增

    Brief Description 一个长度为n的大数,用S1S2S3...Sn表示,其中Si表示数的第i位,S1是数的最高位,告诉你一些限制条件,每个条 件表示为四个数,l1,r1,l2,r2,即两 ...

  8. BZOJ4569 [Scoi2016]萌萌哒(并查集,倍增)

    类似\(ST表\)的思想,倍增\(log(n)\)地合并 你是我家的吗?不是就来呀啦啦啦.还有要来的吗?没了!那有多少个家就映射多少答案呀 倍增原来这么好玩 #include <iostream ...

  9. 【BZOJ4569】[Scoi2016]萌萌哒 倍增+并查集

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

  10. [BZOJ4569] [Luogu 3295] [SCOI2016]萌萌哒(并查集+倍增)

    [BZOJ4569] [Luogu 3295] [SCOI2016]萌萌哒(并查集+倍增) 题面 有一个n位的十进制数a(无前导0),给出m条限制,每条限制\((l_1,r_1,l_2,r_2)(保证 ...

随机推荐

  1. 织梦cms/dedecms清理冗余废弃未引用图片方法

    原理描述: 在原有织梦后台菜单中增加"清理冗余图片按钮",实现清理冗余图片的功能. 操作步骤: 1. 打开后台dede\sys_sql_query.php代码 在该文件中搜索如下代 ...

  2. python 常用算法学习(2)

    一,算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限时间内获得所要求 ...

  3. 自动化服务部署(一):Linux下安装JDK

    自动化测试的主要目的是为了执行回归测试.当然,为了模拟真实的用户操作,一般都是在UAT或者生产环境进行回归测试. 为了尽量避免内网和外网解析对测试结果的影响,将自动化测试服务部署在外网的服务器是比较好 ...

  4. OAuth2.0学习(1-9)新浪开放平台微博认证-web应用授权(授权码方式)

    1. 引导需要授权的用户到如下地址: URL 1 https://api.weibo.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&respons ...

  5. redis数据库各种数据类型的增删改查命令

    redis的常用数据操作: redis是key-value的数据结构,每条数据都是一个键值对. 键的类型是字符串并且键不能重复. redis最基本数据类型是string 所以下面的操作可以省略引号&q ...

  6. mangodb的基本操作:增删改差

    MongoDB三元素: 1 数据库: 和关系型数据库中数据库的层次相同,内部可以有多个集合. 2 集合: 相当于关系型数据库中的表,存储若干文档,结构不固定 3 文档: 相当于关系型数据库中的行,是J ...

  7. mybatis配置多数据源(利用spring的AbstractRoutingDataSource)

    主要是利用了spring的AbstractRoutingDataSource. 直接上配置了: spring-mybatis.xml <bean name="dataSource&qu ...

  8. Python基础(函数-递归)

    本章内容: 深浅拷贝 函数(全局与局部变量) 内置函数 文件处理 三元运算 lambda 表达式 递归(斐波那契数列) 冒泡排序 深浅拷贝 一.数字和字符串 对于 数字 和 字符串 而言,赋值.浅拷贝 ...

  9. 一大波 Android 刘海屏来袭,全网最全适配技巧!

    一.序 Hi,大家好,我是承香墨影! Apple 一直在引领设计的潮流,自从 iPhone X 发布之后,"刘海屏" 就一直存在争议.不过不管你怎样,Android 也要跻入 &q ...

  10. netcore webapi帮助文档设置

    如何建 .netcore webapi 项目这个就不说了,这个都没有没必要看下去. 我这里是.netcore 2.0,虽然没测过1.0的,但想来差不多. 1.Nuget Packages安装,使用程序 ...