首页 > 代码库 > uva 10413 - Crazy Savages(拓展欧几里得)
uva 10413 - Crazy Savages(拓展欧几里得)
题目链接:uva 10413 - Crazy Savages
题目大意:一座山有m个山洞,形成一个圈,现在有n个部落的人,每个部落一开始住在ci山洞,第2天会向后面移动pi个位置,一共会在这座山住li天。现在如果两个部落在同一个山洞相遇,则会发生战争,问说m最小时多少的时候,保证不会发生争斗。
解题思路:因为每个部落都有自己的存在时间,所以枚举m,然后枚举两个部落,判断他们有没有可能相遇。
假设在第k天:
ci+k?pi=a?m???(1)
cj+k?pj=b?m???(2)
由(2)-(1)得
(ci?cj+k?(pi?pj)=(a?b)?m
令A=pj?pi,B=m,C=ci?cj
然后就有A?k+B?(a?b)=C
用拓展欧几里得求出k的通解,看有没有满足0≤k≤min(li,lj)的解,有的话表示会相遇。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 20;
const int maxans = 1e6;
const int INF = 0x3f3f3f3f;
struct Sava {
int c, p, l;
}s[maxn];
int n;
void gcd (int a, int b, int& d, int& x, int& y) {
if (b == 0) {
d = a;
x = 1;
y = 0;
} else {
gcd(b, a%b, d, y, x);
y -= (a/b) * x;
}
}
bool judge (int m) {
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
int A = s[j].p - s[i].p;
int C = s[i].c - s[j].c;
int L = min(s[i].l, s[j].l);
int d, x, y;
gcd(A, m, d, x, y);
if (C % d)
continue;
int up = INF, lower = -INF;
if (m / d > 0) {
up = min(up, (int)floor( (L * d * 1.0 - x * C * 1.0) / m));
lower = max(lower, (int)ceil( (-x * C * 1.0) / m));
} else {
up = min(up, (int)floor( (-x * C * 1.0) / m));
lower = max(lower, (int)ceil( (L * d * 1.0 - x * C * 1.0) / m));
}
if (up >= lower)
return false;
}
}
return true;
}
int main () {
int cas;
scanf("%d", &cas);
while (cas--) {
int star = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &s[i].c, &s[i].p, &s[i].l);
star = max (star, s[i].c);
}
for (int i = star; i <= maxans; i++) {
if (judge(i)) {
printf("%d\n", i);
break;
}
}
}
return 0;
}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。