Pseudoforest 【HDU - 3367】【並查集+(可以忽略的離散化)】
題目連結
翻譯的有點不準確,還是靠自我的理解吧,吶,具體是這樣的:第一行 N, M, 接下來有M行,N代表有幾個字母組成, M代表有多少個可操作區間。
然後講一下幾個測試樣例:
樣例一:
表示只有一個字母,這個字母可以是a.....z, 1代表下面只有一個操作區間,就是1 1,
當這個字母是a時, 它經過1 1這個操作區間進行有限次的“增加”後,可以變成b,c,d....z,那麼a和b,....z就是同一種鎖,
當這個字母是b時, 它經過1 1這個操作區間進行有限次的“增加”後,可以變成a, c,d....z,因為a,....z已經是同一種鎖了,,如果這個字母是c....,後面就是一樣的,永遠是這26個字母,說明是唯一的解:ans==1
樣例二:
2 1 1 2
意思是有兩個字母,以及一次操作,為1~2:當這兩個字母是ab,在可操作區間1 2,它可以變成bc,cd,.....za;那麼ab和bc,cd,.....za就是同種鎖;當這兩個字母是bc時, 當這兩個字母是cd時......等等,這都和當字母是ab時相同,這算一種鎖;當字母是ac時,字母ac 和 bd.......zb都是屬於同種鎖;發現,後面的可能只會隨著首字與第二字元的大小來產生個數,第二字元與第一字元的差距可以為0~25,%26只有這26種可能。ans==26。
那麼這該如何解呢?尤其是第一個樣例還有1~1這樣的區間,我們該如何求解?譬如待查詢區間為L~R,那麼,我們把他們化為L~R+1也沒多少區別?為什麼這麼說呢?我們該如何求解這到底有多少種方案數,如果有一組相互對應,那麼26的N次方就會少一組,這個可以自推。然後,為了避免重複,我們將原區間看作L~R+1
我在這題中還用了離散化的思想(題看錯了,資料看大了),不過可以看下,就當練習自己離散化能力了。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 using namespace std; typedef unsigned long long ull; const int mod=1e9+7; const int maxN=1005; typedef long long ll; int N, M, m, a[maxN<<1], root[maxN<<1], diff, num[maxN<<1], cnt; bool cmp(int e1, int e2) { return e1<e2; } map<int, int> mp; void init() { cnt=0; mp.clear(); for(int i=1; i<=m; i++) { root[i]=i; } } ll fast_mi(ll x, int y) { ll ans=1; while(y) { if(y&1) ans = (ans*x)%mod; x = (x * x)%mod; y>>=1; } return ans; } struct Eddge { int no, to; Eddge(int a=0, int b=0):no(a), to(b) {} }edge[maxN]; int fid(int x) { return x==root[x]?x:(root[x]=fid(root[x])); } void mix(int x, int y) { int u=fid(x), v=fid(y); if(u != v) { root[u] = v; cnt++; } } int main() { while(scanf("%d%d", &N, &M)!=EOF) { m = 2*M; for(int i=1; i<=M; i++) { scanf("%d%d", &edge[i].no, &edge[i].to); a[2*i-1] = edge[i].no; a[2*i] = edge[i].to + 1; } init(); sort(a+1, a+1+m, cmp); diff = (int)(unique(a+1, a+1+m) - a - 1); //printf("diff: %d\n", diff); for(int i=1; i<=diff; i++) { mp[a[i]]=i; //printf("%d\n", a[i]); } for(int i=1; i<=M; i++) { mix(mp[edge[i].no], mp[edge[i].to+1]); } printf("%lld\n", fast_mi(26, N-cnt)%mod); } return 0; }