天天寫演算法之Code Lock
阿新 • • 發佈:2019-01-23
這個題目不是很好理解,就是給你n個字母組成的密碼,每個字母有26中選擇,再給出幾個區間,這個區間內的字母可以同時加1變換。也就是abc,如果ab是同一個區間,那麼就可以實現同時變換,也就是ab變成bc可以通過一次變換(幾個個區間)得到的認為是同意把鎖。問這樣的密碼一共有多少種。比如 abc,如果ab是可以同時變換的,此時c有26中,也就是可以取遍26種字母。而如果沒有限制那麼a和b其實也各有26中,也就是26*26種。但是可以通過序列變換得到的那麼就認為相同,所以,如果開始是ab,那麼bc cd。。。。都一樣,轉一圈也就是26中情況相同,因此需要/26,所以當有一個區間時,就需要/26.
能想到並查集我也覺得很不可思議。查詢有多少個不重合的區間。需要一個小trick也就是(1 3)(4 5)=(1 5)而(1 3)(3 5)!=(1 5),為了解決這種情況,我們把left進行減一,也就是使其可以相互連線。
結果如下:#include <iostream> #include <string> #include<string.h> #include<cstdio> using namespace std; #define repf(i,from ,to) for(int i =from;i<=to;i++) #define MAX 10000011 //10000000+10 #define Base 1000000007 //方向為左上右下 int pre[MAX]; int num_block,n,m; void init(int n) { repf(i,0,n)//注意這個地方,因為後面l-1了,所以這裡要從0開始,而不能從1開始,一開始從1開始,wa了好幾次 { pre[i]=i; } num_block = 0 ; } int Find(int x ) { if(pre[x]!=x) { pre[x] = Find(pre[x]); } return pre[x]; } int Merge(int a ,int b ) { int fa = Find(a); int fb = Find(b); if(fa!=fb) { pre[fa]=fb; num_block++; } } long long quickMul(int a ,int b) { long long sum =1 ; int k = b; long long t=a; while(k) { if(k&1) { sum = (sum*t)%Base; } t=(t*t)%Base; k>>=1; } return sum ; } int main(){ int left,right; while(cin>>n>>m) { init(n); repf(i,1,m) { cin>>left>>right; Merge(left-1,right); } cout << quickMul(26,n-num_block)%Base<<endl; } return 0 ; }