hdu 3461 Code Lock(并查集)2010 ACM-ICPC Multi-University Training Contest(3)
想不到这还可以用并查集解,不过后来证明确实可以……
题意也有些难理解——
给你一个锁,这个所由n个字母组成,然后这个锁有m个区间,每次可以对一个区间进行操作,并且区间中的所有字母要同时操作。每次操作可以将区间中所有字母+1。即把a变成b,把z变成a。
举个例子,比如有一个锁,由abcdef组成,前三个字母abc是一个区间,第四五个字母de是一个区间,那么如果对abc操作一次,则获得新锁bcddef,再对de区间操作一次,得bcdeff。但是,最后一个字母f是不能操作的。
如果一把锁通过对可操作区间的有限次操作可以得到另一个锁,那么我们说这两个锁是相同的,请求出在已给的长度和区间的情况下一共有多少种不同的锁。
输入:
第一行包括两个整数n, m。n表示这个锁的字符长度,m表示可操作区间个数。
接下来m行,每行包括两个整数a, b,表示一个从a到b的区间。
输出:
输出不同的锁的数量,结果Mod100000007。
经过分析发现——
1. 如果没有区间,那么有26^n种锁。
2. 如果有一个长度为1的区间(例如abcdef中的(1, 1),即字符'a'),那么因为这个区间中无论第一个字符为什么,经过有限次变换都可以成为a,那么只要后5个字符和"abcdef"相同,则是同一把锁,所以有26^(n-1)种不同的锁。
3. 如果有一个长度为k(k <= n)的区间(例如abcdef中的(1, 3),即"abc"),那么,只要前三个字符ASSIC码依次增1的字符串(如abc, bcd, xyz),只要其余字符与"abcdef"相同,则都可以通过有限次的变换得到"abcdef"。因此,有26^(n-1)种不同的锁。
4. 如果在"abcdef"中,同时存在三个区间(1, 3), (4, 5), (1, 5),因为变换(1, 5)等价于同程度变换(1, 3), (4, 5),所以可以忽略三者中的一个,认为存在两个区间。因此,存在26^(n-2)种不同的锁。
5. 在"abcdef"中,区间(1, 3), (3, 5), (1, 5)是不同的。因为旋转(1, 3)t次后,再旋转(3, 5)t次,会将第3个字符旋转2*t次,而其他字符旋转t次,不等价于旋转(1, 5)t次。所以共计存在3个区间。因此,存在26^(n-3)种不同的锁。
综上,忽略重复的区间,剩下的区间数为tmp,则存在26^(n-tmp)种不同的锁。
此时,就是最神奇的转换——我们可以使用并查集来去掉那些重复的区间。合并的状态是区间的左右坐标,我们将每个区间的左右坐标分别用l, r表示。因为结论(4)(5),可以将每个区间的坐标看做(l-1, r)。
以上是我看题解+自己理解得到的一些结论,那个转换成并查集实在是太精彩了。许多题目不仅需要缜密的分析,许多时候还需要思维的转换。当然了,见多才能识广,为什么可以举一反三?不仅因为才思敏捷,更因为在这之前已经见了三十,三百,乃至三千了。当然,足够的独立思考是很重要的,虽然每个人对于学与思的要求不一样,但我们要把握好最适合自己的度,取得近似最优解。
废话说完,上代码——
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define LL long long //坑爹的东西
using namespace std; const int N = ;
const int M = ; int fm[N];
LL ans, n, m, tmp; int mfind(int x)
{
int fx = x;
while(fx != fm[fx]) fx = fm[fx]; //查询
while(x != fm[x]) //路径压缩
{
int mid = fm[x];
fm[x] = fx;
x = mid;
}
return fx;
} void mmerge(int x, int y)
{
int fx = mfind(x);
int fy = mfind(y);
if(fx != fy) //合并(如果父节点相同,则是存在一个可以忽略的区间)
{
fm[fx] = fy;
tmp++; //不可忽略的可操作区间
}
} LL qpow(LL x, LL y) //快速幂
{
if(y == ) return ;
LL rt = ;
while(y > )
{
if(y%)
{
rt *= x;
rt %= M;
}
y /= ;
x *= x;
x %= M;
}
return (rt*x)%M;
} int main()
{
//freopen("test.txt", "r", stdin);
while(~scanf("%lld%lld", &n, &m))
{
tmp = ;
for(int i = ; i <= n; i++) fm[i] = i;
for(int i = ; i < m; i++)
{
int a, b;
scanf("%d%d", &a, &b);
mmerge(a-, b);
}
//printf("%d ", tmp);
printf("%lld\n", qpow(, n-tmp));
}
}
hdu 3461 Code Lock(并查集)2010 ACM-ICPC Multi-University Training Contest(3)的更多相关文章
- HDU 3461 Code Lock(并查集+二分求幂)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3461 A lock you use has a code system to be opened in ...
- HDU 3461 Code Lock(并查集,合并区间,思路太难想了啊)
完全没思路,题目也没看懂,直接参考大牛们的解法. http://www.myexception.cn/program/723825.html 题意是说有N个字母组成的密码锁,如[wersdfj],每一 ...
- hdu 3461 Code Lock 并查集(有点难想到)★★
#include<stdio.h> #include<math.h> ]; int count; #define mod 1000000007 int find(int x) ...
- hdu 3938 Portal(并查集+离线+kruskal)2011 Multi-University Training Contest 10
搜了题解才把题搞明白.明白之后发现其实题意很清晰,解题思路也很清晰,只是题目表述的很不清晰…… 大意如下—— 给你一个无向图,图中任意两点的距离是两点间所有路径上的某一条边,这条边需要满足两个条件:1 ...
- HDU 3461 Code Lock(并查集)
很好的一个题,思想特别6 题意:给你小写字母个数n,每个字母可以向上翻动,例如:d->c,a->z.然后给你m对数(L,R)(L<=R),表示[L,R]之间可以同时向上翻动,且翻动后 ...
- HDU 3461 Code Lock(并查集的应用+高速幂)
* 65536kb,仅仅能开到1.76*10^7大小的数组. 而题目的N取到了10^7.我開始做的时候没注意,用了按秩合并,uset+rank达到了2*10^7所以MLE,所以貌似不能用按秩合并. 事 ...
- HDU 3461 思维+并查集
Code Lock 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3461 Problem Description A lock you use has ...
- hdu 3461 Code Lock
http://acm.hdu.edu.cn/showproblem.php?pid=3461 并差集和幂取模 这道题主要是求不可操作区间. #include <cstdio> #inclu ...
- HDU 1811 拓扑排序 并查集
有n个成绩,给出m个分数间的相对大小关系,问是否合法,矛盾,不完全,其中即矛盾即不完全输出矛盾的. 相对大小的关系可以看成是一个指向的条件,如此一来很容易想到拓扑模型进行拓扑排序,每次检查当前入度为0 ...
随机推荐
- c#操作剪切板
C#定义了一个类System.Windows.Forms.Clipboard来简化剪切板操作,这个类有一个静态方法,主要有: Clear 清除剪切板中的所有数据: ContainsData,Conta ...
- LINUX下如何查看tomcat运行状态,判断其是否启动
1,查看Tomcat启动日志. ${catalina_home}\logs [root@iZ25b4ffkfaZ logs]# tail -f catalina.outSep 10, 2015 11: ...
- hdu 3441 Rotation
总的来说,这题要2次用到polya定理. 由题目条件A*A=B*B+1,变形为(A-1)*(A+1)=K*B*B; 分别分解A-1和A+1的质因数,在合并在一起. 第一步:搜索B,对B*B的正方形涂色 ...
- cojs 疯狂的求和问题 解题报告
QAQ 好久不在cojs上出题了 最近学了点新科技,于是就做成题来分享了 这道题是要求simga(i^k) 那么就先说说部分分的算法吧: 10分: 直接暴力就可以了,时间复杂度O(nlogk) 30分 ...
- python 字符串格式化 输出
1. 需要输出3列,为了输出好看,需要制定每一列的宽度: ‘%6.2f’ % 1.235 # 长度为6,保留2为小数 print '{0:20} {1:<20} {1:<20}\r\n'. ...
- PostMessage与SendMessage各自的问题
深入解析SendMessage.PostMessage 本文将使用C++语言,在MFC框架的配合下给出PostMessage.SendMessage等的使用方式与使用不当造成的后果(讨论均针对自定义 ...
- 233. Number of Digit One
题目: Given an integer n, count the total number of digit 1 appearing in all non-negative integers les ...
- 54. Spiral Matrix
题目: Given a matrix of m x n elements (m rows, ncolumns), return all elements of the matrix in spiral ...
- Spring中的mappingResources和mappingDirectoryLocations
今天使用Spring+Hibernate进行事务管理,按照顺序也就是配置,DataSource,Sessionfactory,事务管理器以及拦截器. DateSource可以直接使用Hibernate ...
- java--面向抽象编程
所谓面向抽象编程是指当设计某种重要的类时,不让该类面向具体的类,而是面向抽象类,及所设计类中的重要数据是抽象类声明的对象,而不是具体类声明的对象.就是利用abstract来设计实现用户需求. 比如:我 ...