标签:并查集
题目链接:点击打开链接
解题思路:
一道看不出来是并查集的并查集题,做来做去还是觉得九野的题集不错。题目大意就是有一个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