[HDU3461] [2010多校联考3] Code Lock [并查集]

题意:给出一个由 N N 个字母组成的锁。
给出 M M 个区间 [ L , R ] [L,R] ,每次操作可以将某个区间中所有字母变为字典序中的下一个字母。
特殊地,‘z’会变成’a’。
如果一把锁通过对可操作区间的有限次操作可以得到另一个锁,那么认为这两个锁是相同的。
请求出一共有多少种不同的锁 % 1 e 9 + 7 \%1e9+7
( N 1 0 7 , M 1 0 3 ) (N\le10^7,M\le10^3)

锁啊,感觉是置换

慢慢推广
如果 M = 0 M=0 A n s = 2 6 N Ans=26^N

如果只有一个可操作区间,长度为 1 1 ,很显然 A n s = 2 6 N 1 Ans=26^{N-1}

如果只有一个可操作区间 [ p , p + k 1 ] [p,p+k-1] ,同样有 A n s = 2 6 N 1 Ans=26^{N-1}

很显然 A n s t o t a l = A n s [ 1 , p 1 ] + A n s [ p , p + k 1 ] + A n s p + k , N Ans_{total}=Ans_{[1,p-1]}+Ans_{[p,p+k-1]}+Ans_{p+k,N}
那么这个区间可以当作 [ 1 , k ] [1,k] 来想,里面有 p 1 , p 2 ,   , p k p_1,p_2,\cdots,p_k k k 个数。
由于把 [ 1 , k ] [1,k] 全部 + 1 +1 并不改变区间内每个数的相对大小,我们记 p i p_i 的相对大小为 p i p 1 p_i-p_1
显然 p 1 p_1 的相对大小永远为 0 0 ,所以 p 1 p_1 对答案没有任何贡献
A n s [ p , p + k 1 ] Ans_{[p,p+k-1]} 相当于 2 6 k 1 26^{k-1} ,那么 A n s t o t a l = 2 6 N 1 Ans_{total}=26^{N-1}

如果只有 k k 个不相交的可操作区间,那么 A n s = 2 6 N k Ans=26^{N-k}

考虑多个区间,有相交部分。

  • 如果存在区间 [ p 1 , p 2 ] , [ p 2 , p 3 ] ,   , [ p n 1 , p n ] [p_1,p_2],[p_2,p_3],\cdots,[p_{n-1},p_n] [ p 1 , p n ] ( p a < p b ( a < b ) ) [p_1,p_n](p_a<p_b(a<b))
    那么区间 [ p 1 , p n ] [p_1,p_n] 存不存在都差不多,显然可以去掉它。问题就是怎么判断这种情况
    我们可以考虑连接 p n p n 1 , p n 1 p n 2 ,   , p 3 p 2 , p 2 p 1 p_n\to p_{n-1},p_{n-1}\to p_{n-2},\cdots,p_3\to p_2,p_2\to p_1
    这个时候遇见了区间 [ p 1 , p n ] [p_1,p_n] ,却发现 p n p_n 已经连在 p 1 p_1 上了,就可以无视这个区间。
  • 而不是上面那种情况的话,显然可以看作这些区间是不相交的。
    于是有几个区间就当作有几个不相交区间算。

所以我们只需要记录有效区间数 c n t cnt A n s = 2 6 N c n t Ans=26^{N-cnt}

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<cctype>
using namespace std;
#define LL long long
const LL MOD=1000000007;
int N,M,x,y,fx,fy,ans=0;
int fa[10000005]={};
LL quick_pow(int T)
{
	LL Ans=1ll,Base=26ll;
	while(T)
	{
		if(T&1)Ans=(Ans*Base)%MOD;
		Base=(Base*Base)%MOD;
		T>>=1;
	}
	return Ans;
}
int find(int x){return (fa[x]==x)?x:(fa[x]=find(fa[x]));}
int main()
{
	while(~scanf("%d%d",&N,&M))
	{
		for(int i=0;i<=N;++i)fa[i]=i; ans=0;
		while(M--)
		{
			scanf("%d%d",&x,&y); --x;
			fx=find(x),fy=find(y);
			if(fx!=fy)fa[fy]=fx,++ans;
		}
		printf("%lld\n",quick_pow(N-ans));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Estia_/article/details/82873771