标签:style blog http color width os
题意:一个岛上有一些山洞,有n个幸存者,每个幸存者初始在山洞Ci,山洞是形成一个环的,每天每个人都会走Pi,然后Li天后该人会死掉,要求一个最小的山洞数使得每个人在活着的时候都不会碰面(因为碰面就会发生冲突)
思路:枚举山洞数m,然后两两判断会不会碰面
判断的方法是:两个人其实就是两个线性方程
(c1+p1k1)%m=x
和 (c2+p2k2)%m=x
如果两人会在同一天碰面,那么两人k值相同,两式相减后得到(c1?c2)+k(p1?p2)=ym,移项后得到一个线性方程
ax+by=c,a=(p1?p2),b=?m,c=(c2?c1),然后利用扩展欧几里得算法去求解判断有没有解在[0,min(k1,
k2)]中,如果有就是会发生冲突,不满足
代码:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; int t, n; struct People { int c, p, l; void read() { scanf("%d%d%d", &c, &p, &l); } } p[20]; bool cmp(People a, People b) { return a.l > b.l; } int exgcd(int a, int b, int &x, int &y) { if (!b) {x = 1; y = 0; return a;} int d = exgcd(b, a % b, y, x); y -= a / b * x; return d; } bool judge(People A, People B, int mod) { int a = A.p - B.p; int b = -mod; int c = B.c - A.c; int x, y; int d = exgcd(a, b, x, y); if (c % d) return false; int down = -INF, up = INF; int tmp = min(A.l, B.l); if (b / d < 0) { down = max(down, (int)ceil((tmp * d - x * c) * 1.0 / b)); up = min(up, (int)floor(-x * c * 1.0 / b)); } else { down = max(down, (int)ceil(-x * c * 1.0 / b)); up = min(up, (int)floor((tmp * d - x * c) * 1.0 / b)); } return down <= up; } bool solve(int mod) { for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) if (judge(p[i], p[j], mod)) return false; return true; } int main() { scanf("%d", &t); while (t--) { scanf("%d", &n); int down = 0; for (int i = 0; i < n; i++) { p[i].read(); down = max(down, p[i].c); } for (int i = down; i <= 1000000; i++) { if (solve(i)) { printf("%d\n", i); break; } } } return 0; }
UVA 10413 - Crazy Savages(数论),布布扣,bubuko.com
标签:style blog http color width os
原文地址:http://blog.csdn.net/accelerator_/article/details/37595149