題目鏈接:點擊打開鏈接
解題思路:
一道看不出來是並查集的並查集題,做來做去還是覺得九野的題集不錯。題目大意就是有一個n位的密碼串,每位可能是a到z間的任意一個字母。m行輸入區間[ l , r],代表這個區間可以同時做+1操作,如果一組密碼通過有限次增加變成另一組密碼,那麼我們認爲這兩組密碼是相同的。求在m個區間下有多少種不同的密碼。
暴力來看是求26^n,當有cnt個不同區間加進來後,答案爲26^(n - cnt)。我們另 f 數組全部初始化爲-1,然後對於區間[ l , r ],我們用f[ l ] = r + 1來表示。每次操作,如果不存在區間[ l , r ],那麼cnt ++。
最後計算下26^(n - cnt)即可。
完整代碼:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <string>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
const int MOD = int(1e9)+7;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-9;
const double PI = acos(-1.0); //M_PI;
int n , m;
const int maxn = 10000001;
int f[maxn];
int find(int x)
{
return f[x] == -1 ? x : find(f[x]);
}
bool unin(int a , int b)
{
int x = find(a);
int y = find(b);
if(x == y) return false;
f[x] = y;
return true;
}
LL pow(int x)
{
LL res = 1;
for(int i = 0 ; i < x ; i ++)
{
res *= 26;
res %= MOD;
}
return res;
}
int main()
{
#ifdef DoubleQ
freopen("in.txt","r",stdin);
#endif
while(cin >> n >> m)
{
memset(f , -1 , sizeof(f));
int cnt = 0;
int l , r;
for(int i = 0 ; i < m ; i ++)
{
cin >> l >> r;
if(unin(l , r + 1))
cnt ++;
}
cout << pow(n - cnt) << endl;
}
}