標籤:演算法 codeforces
這是 Codeforces Round #292 (Div. 2)的一道題,原題在這裡,題意就是:
小明有n個男同學(編號為 0 ~ n-1)和m個女同學 (編號為 0 ~ m-1),小明要安排男女之間約會,如何安排約會呢,假設時間是i (i >=0) ,小明在 i 天就邀請 i % n 號男同學,和 i % m 號女同學約會,如果男女同學之間有一個是快樂的,那麼兩個人都是快樂的,那麼問題來了,小明能否使他們全部都快樂?
我當時是這樣想的,要是n和m相等的話,那麼要是在編號區間 [0, n)之間都有人快樂,例如,
例a:
要是n = m = 3, n 中快樂的有 0、1, m 中快樂的有 2,那麼全部人在約會後都會快樂。
要是n 和 m 不想等呢? 問題來了,然後這個時間要怎麼聯絡起來?
我當時想不出,類比這個約會的過程,用O(n * m) 的方法,結果被hack了一下,水爆了 = =、 看了editorial後才明白的。
好了,回到問題,要是n 和m 不想等的時候呢,假設n = 2 , m = 3,則在時間 i = 2 後,在男生中 2%2 = 0 號男生與 2%3 = 2 號女生約會,可以把m 中的2 號女生看作一個,與 兩個男生約會,問題就變成了 n = 2, m = 1, 之所以要這麼做,是為了找出一個區間,這個區間滿足,每個編號都有人快樂, 就像前面例a 一樣。然後繼續,n = 2, m = 1時,在時間i = 1 時,男生中 1 % 2 = 1 號男生與 1 % 1 = 0 號女生約會,把 n 中的1 號男生看作一個,與1個女生約會,問題就編程了 n = m = 1, 這樣,就達到了之前說的一個目的,找到區間[0, 1) 要是這個內對應的編號都有人快樂,那麼全部人都會快樂。先設 c 是 n 和 m 的最大公約數,在 n = 2, m = 3, i = 2 時,這樣變換, n = 2, m = m % n = 1, i 在累加時也這樣做,最後把問題變換為 n = m = 1, 這樣,只要區間之間
[0, 1) 之間對應的編號都有人快樂,那麼全部人都會快樂。是不是很像gcd,在例子a 中,因 0、1 號是快樂的,那麼0 % 1 = 0, 1 % 1 = 1,會因為他們而快樂,所以,每個快樂的人的編號去模n和m的公約數,就求出因為他們而快樂的人的編號。好了,說了一大堆沒有邏輯的話,該上代碼了。
#include <stdio.h>#include <iostream>#include <map>#include <string.h>using namespace std; int gcd(int a, int b){ int c, d; d = max(a, b); c = min(a, b); if(d%c == 0) return c; else return gcd(d%c, c);}int pep[101];int main(){ int n, m, b, g, c, i, cnt = 0, id; // freopen("e:/in.txt", "r", stdin); memset(pep, 0, sizeof(pep)); cin >> n >> m; c = gcd(n, m); cin >> b; for( i = 0; i < b; i++ ){ cin >> id; if(!pep[id%c]) pep[id%c] = 1, cnt++; } cin >> g; for( i = 0; i < g; i++ ){ cin >> id; if(!pep[id%c]) pep[id%c] = 1, cnt++; } if(cnt == c) cout << "Yes"; else cout << "No"; return 0;}
B. Drazil and His Happy Friends