题意:对于一个锁你可以用一个密码系统代替钥匙去打开它, 一个钥匙包含了一系列的齿轮 ,每一个齿轮上有a到z顺序的小写字母,如果你向上滑动齿轮,那么它的字母会是当前字母字典序的下一个,(z的下一个是a), 每一次操作你只被允许滑动一些特定字串中连续的齿轮 ,这样做和滑动字串中每一个齿轮的效果是一样的。经过一系列的作,一个锁如果变成了其它的形式,我们可以认为它们是相同的锁。、
问你:找出存在多少个不同的锁。一个锁有n位密码,一共有26^n种可能,里面用“重复的”,下列给出的m个区间,可以有26^m种可能,但是题目要求“At each operation,you are only allowed to move some specific subsequence of contiguous wheels up. This has the same effect of moving each of the wheels up within the subsequence.” 1--3,4--5,和1--5是一样的,所以用并差集去重,结果为26^(n-cnt)(cnt为去重后的个数)。
#include<iostream>
#include<cstring>
#include<cstdio>
#define mod 1000000007
#define ll long long
using namespace std;
const int N=10000000+5;
int n,m;
int cnt;
class UF
{
public:
inline void Init()
{
cnt=0;
for(int i=0;i<=n;i++)
father[i]=i;
}
inline int find(int x)
{
if(x!=father[x])
{
father[x]=find(father[x]);
}
return father[x];
}
inline void union_set(int a,int b)
{
if(a==b) return;
cnt++;
father[a]=b;
}
private:
int father[N];
}uf;
ll fuck(ll x,int k)
{
ll res=1;
while(k!=0)
{
if(k%2!=0)
{
res=((res%mod)*(x%mod))%mod;
}
k/=2;
x=((x%mod)*(x%mod))%mod;
}
return res;
}
void Input()
{
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d %d",&a,&b);
a--;
int ra=uf.find(a);
int rb=uf.find(b);
if(ra!=rb)
{
uf.union_set(ra,rb);
}
}
}
void treatment()
{
printf("%lld\n",fuck(26,n-cnt)%mod);
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
uf.Init();
Input();
treatment();
}
return 0;
}