HDU-3461 Code Lock 并查集 + 二分求幂

题目链接

题意是说有N个字母组成的密码锁, 如【wersdfj】,   每一位上的字母可以转动, w可转动变成x, z变成a。但是题目规定, 只能同时转动某个区间上的所有字母, 如【1,3】, 那么第1到第3个的所有字母要同时转动,那么【 wersdfj 】经过一次操作就变成 【 xfssdfj 】.    一共有M 个区间是可以操作的。  

题目还规定:If a lock can change to another after a sequence of operations, we regard them as same lock. 

就是说, 经过可操作区间进行的操作得到的所有锁情况,都是同一个的。 也就是说,所有不同的锁就是“不可操作区间”的所有组合情况。


在最初时,每个字母看作是一个独立的区间, 那么就有N个区间, 可以很容易地用初始化的并查集来表示。然后一个区间可以看作是一个“元素”,  我们只需要求出共有多少个可操作区间x, 然后就可以计算得到N-x个不可操作的区间。 不可操作区间的所有组合,就是能组成的所有不同的锁。

每个区间可以有26种情况, 那么就共有26^(N-x)种情况。由于N可能会很大,所以直接计算浪费时间了,用二分求幂法来计算出结果。


#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int maxn = 10000005;
const int inf = 1<<30;
const __int64 MOD = 1000000007;
int n,m,ans;
int p[maxn];
int find(int x)  
{  
    return x!=p[x]?p[x]=find(p[x]):x;  
} 
void merge( int a,int b )
{
	int x = find(a);
	int y = find(b);
	if( x != y ){
		p[x] = y;
		ans ++;
	}
}
void init()
{
	ans = 0;
	for( int i = 0; i <= n; i ++ )
		p[i] = i;
}
__int64 fun( int x )
{
	__int64 sum = 1,tmp = 26;
	while( x ){
		if( x&1 ){
			sum = sum * tmp;
			sum %= MOD;
		}
		tmp = (tmp*tmp)%MOD;
		x >>= 1;
	}
	return sum;
}
int main()
{
    //freopen("data.txt","r",stdin);   
	int l,r;
	while( scanf("%d%d",&n,&m) != EOF ){
		init();
		for( int i = 0; i < m; i ++ ){
			scanf("%d%d",&l,&r);
			merge( l-1,r );
		}
		printf("%I64d\n",fun(n-ans)%MOD);
	}
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值