原 A-B數對(加強版)參見P1102ui
克里特島以野人羣居而著稱。島上有排列成環行的M個山洞。這些山洞順時針編號爲1,2,…,M。島上住着N個野人,一開始依次住在山洞C1,C2,…,CN中,之後每一年,第i個野人會沿順時針向前走Pi個洞住下來。this
每一個野人i有一個壽命值Li,即生存的年數。spa
下面四幅圖描述了一個有6個山洞,住有三個野人的島上前四年的狀況。三個野人初始的洞穴編號依次爲1,2,3;每一年要走過的洞穴數依次爲3,7,2;壽命值依次爲4,3,1。code
奇怪的是,雖然野人有不少,但沒有任何兩個野人在有生之年處在同一個山洞中,使得小島一直保持和平與寧靜,這讓科學家們非常驚奇。他們想知道,至少有多少個山洞,才能維持島上的和平呢?blog
輸入格式:get
第1行爲一個整數N(1<=N<=15),即野人的數目。string
第2行到第N+1每行爲三個整數Ci, Pi, Li (1<=Ci,Pi<=100, 0<=Li<=106 ),表示每一個野人所住的初始洞穴編號,每一年走過的洞穴數及壽命值。it
輸出格式:io
僅包含一個數M,即最少可能的山洞數。輸入數據保證有解,且M不大於10^6。class
對於50% 的數據:N 的範圍是[1…1,000]。
對於另外50% 的數據:N 的範圍是[1…100,000]。
對於100% 的數據:C 的範圍是[1…1,000,000,000],N 個整數中每一個數的範圍是:[0…1,000,000,000]。
我竟然切了一道紫題??!!好開心qwq
設第$i$我的的壽命爲$x_i$,每次走$y_i$,剛開始在$a$,
若洞穴數爲$b$,那麼咱們須要找到最小的$b$知足對於任意的兩個野人$i,j$
$a_i+y_i * T_i \not \equiv a_j + y_j + T_j \pmod b$,$T$表示第幾年。
而後這個是個標準的歐幾里得式子
枚舉一個$b$,判斷就行了
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int MAXN = 16, B = 31; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N; struct Node { int bg, step, life; bool operator < (const Node &rhs) const { return this -> step < rhs.step; } }a[MAXN]; int x, y; int exgcd(int a, int b, int &x, int &y) { if(b == 0) { x = 1, y = 0; return a; } int r = exgcd(b, a % b, x, y); int tmp = x; x = y, y = tmp - (a / b) * y; return r; } bool check(int X) { for(int i = 1; i <= N; i++) { for(int j = 1; j <= i - 1; j++) { int B = X; int A = a[i].step - a[j].step, C = a[j].bg - a[i].bg, r = __gcd(A, B); if(C % r != 0) continue; A = A / r; B = B / r; C = C / r; exgcd(A, B, x, y); x = (x * C) % B; while(x < 0) x += B; if(x <= a[i].life && x <= a[j].life) return 0; } } return 1; } main() { #ifdef WIN32 freopen("a.in", "r", stdin); #endif N = read(); int fuck = 0; for(int i = 1; i <= N; i++) a[i].bg = read(), a[i].step = read(), a[i].life = read(), fuck = max(fuck, a[i].bg); sort(a + 1, a + N + 1); for(int i = fuck; i <= 1e6; i++)//必定要從最大值開始,,好坑。。 if(check(i)) {printf("%d\n", i); exit(0);} }