想不到这还可以用并查集解,不过后来证明确实可以……

题意也有些难理解——

给你一个锁,这个所由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)的更多相关文章

  1. 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 ...

  2. HDU 3461 Code Lock(并查集,合并区间,思路太难想了啊)

    完全没思路,题目也没看懂,直接参考大牛们的解法. http://www.myexception.cn/program/723825.html 题意是说有N个字母组成的密码锁,如[wersdfj],每一 ...

  3. hdu 3461 Code Lock 并查集(有点难想到)★★

    #include<stdio.h> #include<math.h> ]; int count; #define mod 1000000007 int find(int x) ...

  4. hdu 3938 Portal(并查集+离线+kruskal)2011 Multi-University Training Contest 10

    搜了题解才把题搞明白.明白之后发现其实题意很清晰,解题思路也很清晰,只是题目表述的很不清晰…… 大意如下—— 给你一个无向图,图中任意两点的距离是两点间所有路径上的某一条边,这条边需要满足两个条件:1 ...

  5. HDU 3461 Code Lock(并查集)

    很好的一个题,思想特别6 题意:给你小写字母个数n,每个字母可以向上翻动,例如:d->c,a->z.然后给你m对数(L,R)(L<=R),表示[L,R]之间可以同时向上翻动,且翻动后 ...

  6. HDU 3461 Code Lock(并查集的应用+高速幂)

    * 65536kb,仅仅能开到1.76*10^7大小的数组. 而题目的N取到了10^7.我開始做的时候没注意,用了按秩合并,uset+rank达到了2*10^7所以MLE,所以貌似不能用按秩合并. 事 ...

  7. HDU 3461 思维+并查集

    Code Lock 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3461 Problem Description A lock you use has ...

  8. hdu 3461 Code Lock

    http://acm.hdu.edu.cn/showproblem.php?pid=3461 并差集和幂取模 这道题主要是求不可操作区间. #include <cstdio> #inclu ...

  9. HDU 1811 拓扑排序 并查集

    有n个成绩,给出m个分数间的相对大小关系,问是否合法,矛盾,不完全,其中即矛盾即不完全输出矛盾的. 相对大小的关系可以看成是一个指向的条件,如此一来很容易想到拓扑模型进行拓扑排序,每次检查当前入度为0 ...

随机推荐

  1. HDU 1753 大明A+B(字符串模拟,简单题)

    简单题,但要考虑一些细节: 前导0不要,后导0不要,小数长度不一样时,有进位时,逆置处理输出 然后处理起来就比较麻烦了. 题目链接 我的代码纯模拟,把小数点前后分开来处理,写的很繁杂,纯当纪念——可怜 ...

  2. Linux下c++通过动态链接库调用类

    http://hi.baidu.com/ablenavy/item/b498901c6826bbf587ad4e33 Linux下的动态链接库叫so,即Shared Object,共享对象.一些函数就 ...

  3. 2014多校第一场J题 || HDU 4870 Rating(DP || 高斯消元)

    题目链接 题意 :小女孩注册了两个比赛的帐号,初始分值都为0,每做一次比赛如果排名在前两百名,rating涨50,否则降100,告诉你她每次比赛在前两百名的概率p,如果她每次做题都用两个账号中分数低的 ...

  4. POJ2002Squares

    http://poj.org/problem?id=2002 题意 : 就是给你很多点的坐标,任取四个,看能组成多少个不同的正方形,相同的四个点,不同顺序构成的正方形视为同一正方形. 思路 : 就是一 ...

  5. Android 通过程序添加桌面快捷方式

    原理:通过代码向 Launcher 中的广播接收者发送广播来创建快捷图标. 首先要声明的权限是: <!--添加图标的权限--> <uses-permission android:na ...

  6. hdu1233

    http://acm.hdu.edu.cn/showproblem.php?pid=1233 最小生成树,kruskal算法 #include<stdio.h> #include<m ...

  7. 360 chrome 国际版能够隐藏用户保存的密码

    用360 chrome 国际版一段时间了,今天发现它一个优点:取消了浏览器保存的密码明文显示! 原生的chrome和枫树都会明文显示密码,360 chrome国际版则只显示保存了密码的域名和账户名.光 ...

  8. Openfire 代码部署报错: Variable references non-existent resource:${workspace_loc:openfire_src}

    Variable references non-existent resource:${workspace_loc:openfire_src} -DopenfireHome=“${workspace_ ...

  9. 李洪强iOS开发之OC[012] -类的声明实现小结

    // //  main.m //  11 - 内容总结 // //  Created by vic fan on 16/7/9. //  Copyright © 2016年 李洪强. All righ ...

  10. 数据类型演示DataTypeDemo

    /***数据类型演示*/public class DataTypeDemo{ public static void main(String[] args){  //直接赋予的值,称为字面量  //by ...