好题啊,虽然题目有点难懂
如果没有区间的话,密钥总共有26^n种
如果有区间的话,有些密钥会被视作相同
比如说区间是[1, 3],那么aaab和cccb是两个相同的密钥
对于区间[1,3] [4,5]和[1,5]
显然[1,5]的情况跟[1,3]和[4,5]的情况重复了
我们只要留着[1,3]和[4,5]就好
按这种方法,最后会被分成下面的区间
_ _ _( _ _ ) _ _ ( _ _ _ _) ( _ )_ _
设区间的总长度是x,看得出来26^(n-x)为密钥数
把区间的L,R分别看成两个节点,两节点间连一条边
前面说的删掉[1,5]的方法在图上就是把有环图改成无环图
可用并查集
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <queue>
#include <map>
using namespace std;
#define INF 1e9
#define maxn 10000010
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define mset(x) memset(x,0,sizeof(x))
const int MOD = 1000000007;
typedef __int64 ll;
int n, m, l, r;
bool vis[maxn];
int pa[maxn];
void init(){
memset(pa, -1, sizeof(pa));
}
int find(int x){
if(pa[x]==-1) return x;
return x = find(pa[x]);
}
int uni(int x, int y){
x = find(x);
y = find(y);
if(x==y)
return 0;
pa[y] = x;
return 1;
}
ll qpow(ll x, ll p){
ll res = 1;
while(p){
if(p&1){
res = (res*x)%MOD;
}
p >>= 1;
x = (x*x)%MOD;
}
return res%MOD;
}
int main(){
// freopen("a.txt","r",stdin);
// freopen(".out","w",stdout);
while(cin>>n>>m){
ll cnt=0;
init();
rep(i,1,m){
scanf("%d%d", &l, &r);
cnt += uni(l, r+1);
}
cout<<qpow(26, n-cnt)<<endl;
}
return 0;
}