标签:并查集
题目链接:点击打开链接
解题思路:
一道看不出来是并查集的并查集题,做来做去还是觉得九野的题集不错。题目大意就是有一个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;
}
}
标签:并查集
原文地址:http://blog.csdn.net/u013447865/article/details/44341685