HDU 3461 Code Lock(并查集的应用+快速幂)
2014-07-09 15:28
267 查看
* 65536kb,只能开到1.76*10^7大小的数组。而题目的N取到了10^7,我开始做的时候没注意,用了按秩合并,uset+rank达到了2*10^7所以MLE,所以貌似不能用按秩合并。
其实路径压缩也可以不用.............
题目的大意:
一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个。再给你M个区间[L,M],表示该区间的字母可以一起同步“增加”(从'a'变为'b'为增1,'z'增1为'a')。假如一组密码按照给定的区间进行有限次的“增加”操作后可以变成另一组密码,那么我们认为这两组密码是相同的。该题的目标就是在给定N、M和M个区间的前提下计算有多少种不同的密码。
根据题意,如果一个可调整的区间都没有的话,答案应该是26的N次方。每当加入一个区间的时候,答案就减少为之前的26分之1(因为该区间的加入使得原本不同的26种情况变得等价了)。因此当有x个“不同的”区间加入进来之后,答案应该为26^(N-x)。
但是还有一些特殊情况需要考虑,一个是同样的区间重复加入是不会改变答案的,这点比较好理解。另一点是如果一个区间可以由其他若干个区间“拼接”而得到,那么它的加入不能改变答案。例如如果已经有了区间[1,3]和[4,5],那么再加入区间[1,5]答案也不会改变,因为[1,5]所能实现的密码变化全都可以由同步执行[1,3]与[4,5]来实现,也就是[1,3]+[4,5]等价于[1,5]。特别要注意的是[1,3]+[3,5]这种情况并不等价于[1,5]。
思路:
所以题目就是求区间的个数了。但是注意的是 【1,3】【4,5】和【1,5】区间是等价的。【1,3】【3,5】和【1,5】又是不等价的的,因为3是重叠的。
如何解决区间个数,用并查集刚好,不过要变化的是merge_set(l-1,r)或者merge_set【l,r+1】这样可以解决,线段的拼接问题。这里要好好想一下。
如何求区间:
并查集, merge_set(l-1,r) or merge_set( l,r+1),这里要好好想一下。通过+1,-1刚好连接上了端点,不是吗?
代码:
其实路径压缩也可以不用.............
题目的大意:
一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个。再给你M个区间[L,M],表示该区间的字母可以一起同步“增加”(从'a'变为'b'为增1,'z'增1为'a')。假如一组密码按照给定的区间进行有限次的“增加”操作后可以变成另一组密码,那么我们认为这两组密码是相同的。该题的目标就是在给定N、M和M个区间的前提下计算有多少种不同的密码。
根据题意,如果一个可调整的区间都没有的话,答案应该是26的N次方。每当加入一个区间的时候,答案就减少为之前的26分之1(因为该区间的加入使得原本不同的26种情况变得等价了)。因此当有x个“不同的”区间加入进来之后,答案应该为26^(N-x)。
但是还有一些特殊情况需要考虑,一个是同样的区间重复加入是不会改变答案的,这点比较好理解。另一点是如果一个区间可以由其他若干个区间“拼接”而得到,那么它的加入不能改变答案。例如如果已经有了区间[1,3]和[4,5],那么再加入区间[1,5]答案也不会改变,因为[1,5]所能实现的密码变化全都可以由同步执行[1,3]与[4,5]来实现,也就是[1,3]+[4,5]等价于[1,5]。特别要注意的是[1,3]+[3,5]这种情况并不等价于[1,5]。
思路:
所以题目就是求区间的个数了。但是注意的是 【1,3】【4,5】和【1,5】区间是等价的。【1,3】【3,5】和【1,5】又是不等价的的,因为3是重叠的。
如何解决区间个数,用并查集刚好,不过要变化的是merge_set(l-1,r)或者merge_set【l,r+1】这样可以解决,线段的拼接问题。这里要好好想一下。
如何求区间:
并查集, merge_set(l-1,r) or merge_set( l,r+1),这里要好好想一下。通过+1,-1刚好连接上了端点,不是吗?
代码:
#include<iostream> #include<cstdio> #include<cstring> #define mod 1000000007 #define N 10000000+10 using namespace std; typedef long long int64; int uset ; //int rank ; int cnt; void make_set(int n) { for(int i=0;i<=n;i++) { uset[i]=i; //rank[i]=1; } } int find_set(int x) { if(uset[x]!=x) uset[x]=find_set(uset[x]); return uset[x]; } void merge_set(int x,int y) { int fx=find_set(x); int fy=find_set(y); if(fx==fy) return; else { uset[fx]=fy; cnt++; } } int64 exp(int n) { int64 res=1; int64 tmp=26; while(n) { if(n&1) res=(res*tmp)%mod; tmp=tmp*tmp%mod; n>>=1; } return res; } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { make_set(n); cnt=0; for(int i=0;i<m;i++) { int l,r; scanf("%d%d",&l,&r); merge_set(l-1,r); } //printf("-->%d\n",n-cnt); printf("%I64d\n",exp(n-cnt)); } return 0; }
相关文章推荐
- HDU-3461 Code Lock 并查集 + 二分求幂
- hdu 3461 Code Lock【并查集+快速幂】
- HDU 3461 Code Lock(并查集的应用+高速幂)
- HDU 3461 Code Lock(并查集,合并区间,思路太难想了啊)
- HDU 3461 Code Lock(并查集)
- hdu 3461 Code Lock(并查集)2010 ACM-ICPC Multi-University Training Contest(3)
- HDU - 3461 Code Lock (并查集和幂运算)
- hdu 3461 Code Lock
- HDU 2818&&POJ 1988 并查集简单应用
- Hdu 1829 A Bug's Life && Poj 1182 食物链 (并查集偏移量的应用)
- hdu 1232 经典并查集应用
- HDU 4496 D-City (并查集的应用)逆向思维
- poj 1703 , hdu 1729 , poj 1182 并查集偏移量应用
- hdu 3038 How Many Answers Are Wrong【并查集的简单应用】
- hdu 1232 经典并查集应用
- HDU 3461 Code Lock
- hdu 3461 Code Lock(并查集+二分求幂)
- HDU3461 Code Lock 并查集应用
- hdu 3635 Dragon Balls 并查集应用记录每个点的转移次数
- hdu-3461-Code Lock-并查集+高次幂取模