hdu3461

题意描述:有一个类似滚轮式的密码锁放在一排共n个,有m种操作每次操作一个区间,且此次操作后的所有密码相同,问最多能形成多少种密码

解决:将区间分为可变部分和不可变部分,没当有可变部分时候总区间数要减去一。因为在可变 区间内第一个滚轮一定是固定的(可以转) 

并查集合并区间后做下快速幂就好了 1 //组合数学+快速幂+并查集

 2 //统一区间内的组合数指数在原先基础上要减去1
 3 //证明可以枚举开始的字母因为是循环的所以第一个字母唯一
 4 //注意边界重叠的情况,初始化要从0开始
 5 
 6 #include<cstring>
 7 #include<cstdio>
 8 #include<algorithm>
 9 typedef long long ll;
10 using namespace std;
11 const int MAX = 10000000+10;
12 const int MOD = 1000000007;
13 int pa[MAX];
14 void make(int n)
15 {
16     for(int i=0;i<=n;i++) pa[i]=i;
17 }
18 int find(int x)
19 {
20     return pa[x]==x? x: pa[x]=find(pa[x]);
21 }
22 int Union(int a,int b)
23 {
24     int fx=find(a);
25     int fy=find(b);
26     if(fx==fy) return 0;
27     else
28     {
29         pa[fx]=fy;
30         return 1;
31     }
32 }
33 ll qmod(ll a,ll n)
34 {
35     ll res=1;
36     while(n>0)
37     {
38         if(n&1) res=res*a%MOD;
39         a=a*a%MOD;
40         n>>=1;
41     }
42     return res;
43 }
44 int main()
45 {
46     int n,m,l,r;
47     while(scanf("%d %d",&n,&m)>0)
48     {
49         make(n); int cnt=0;
50         for(int i=0;i<m;i++)
51         {
52             scanf("%d %d",&l,&r);
53             if(Union(l-1,r)) cnt++;
54         }
55         ll ans=qmod(26,(ll)(n-cnt));
56         printf("%I64d\n",ans%MOD);
57     }
58     return 0;
59 }
posted @ 2014-01-24 16:31  acvc  阅读(326)  评论(0编辑  收藏  举报