题意:
有m个洞穴成一个环状,现在有n个野蛮人,给你每个野蛮人的初始位置c[i],每个野蛮人下一天要去顺时针的第p[i]个洞穴,每个野蛮人存活天数为l[i],如果某一天两个野蛮人来到同一个洞穴,就会打架了~必须要死一个了~现在给你所有的条件除了m,问m至少为多少才能保证没有野蛮人打架死亡的。
解题思路:
枚举m,初始的m由输入数据决定,如果第i个人和第j个人在某一天碰到一起了,可以这样表示
(c[i] + x*p[i])%m = (c[j] + x*p[j])%m,即:c[i] + x*p[i] = c[j] + x*p[j] + y*m(x,y为未知数),问题就转换成二元一次方程求解了,扩展欧几里得简单搞起。
/* ********************************************** Author : JayYe Created Time: 2013/10/1 16:50:11 File Name : JayYe.cpp *********************************************** */ #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; //扩展欧几里得 int exgcd(int a, int b, int &x, int &y) { if(!b) { x = 1; y = 0; return a; } int ret = exgcd(b, a%b, y, x); y -= a/b*x; return ret; } int c[22], p[22], l[22], n; bool solve(int m) { for(int i = 0;i < n; i++) { for(int j = i+1;j < n; j++) { int x, y; int d = exgcd(p[j]-p[i], m, x, y); if( (c[i]-c[j])%d ) continue; x *= (c[i]-c[j])/d; if(d < 0) d = -d; x = (x%(m/d) + m/d)%(m/d); // 在两个人都没死之前碰面 if(x <= l[i] && x <= l[j]) return false; } } return true; } int main() { int t; scanf("%d", &t); while(t--) { scanf("%d", &n); int ans = 0; for(int i = 0;i < n; i++) { scanf("%d%d%d", &c[i], &p[i], &l[i]); c[i]--; // 从0开始方便处理 ans = max(ans, c[i] + 1); } while(true) { if(solve(ans)) break; ans++; } printf("%d\n", ans); } return 0; }