BZOJ1407
-
题目
-
分析
考虑位置移动后相等的情况。。
c i + x p i ≡ c j + x p j ( m o d n ) c_i + xp_i \equiv c_j + xp_j \pmod n ci+xpi≡cj+xpj(modn) n n n 为山洞数x ( p i − p j ) ≡ c j − c i ( m o d n ) x(p_i - p_j) \equiv c_j - c_i \pmod n x(pi−pj)≡cj−ci(modn) 化简后即为同余方程
x ( p i − p j ) + n y = c j − c i x(p_i-p_j) + ny = c_j-ci x(pi−pj)+ny=cj−ci 当方程有解时:
g c d ( ( p i − p j ) , n ) ∣ c j − c i gcd((p_i-p_j),n) | c_j - c_i gcd((pi−pj),n)∣cj−ci , x = x × ( c j − c i ) / g c d ( ( p i − P − j ) , n ) x = x \times (c_j-c_i) / gcd((p_i-P-j),n) x=x×(cj−ci)/gcd((pi−P−j),n)
算出最小正整数解和 l [ i ] , l [ j ] l[i],l[j] l[i],l[j] 进行比较,若 ≤ m i n ( l [ i ] , l [ j ] ) \leq min(l[i],l[j]) ≤min(l[i],l[j]) 则说明在 i , j i,j i,j 两个野人在有生之年会跑到同一个点上去,那么就会发生冲突,显然不行。。还有方程无解,显然是不会发生冲突的直接 c o n t i n u e continue continue ,即可。
有了判断之后,就可以枚举山洞数,找出满足条件的最小山洞数。
坑点: g c d ( p i , p j ) gcd(p_i,p_j) gcd(pi,pj) 可能为负数。。。
-
代码
int n; struct node { ll c; ll p; ll l; } a[20]; ll exgcd(ll a, ll b, ll &x, ll &y) { if (b == 0) { x = 1, y = 0; return a; } int d = exgcd(b, a % b, x, y); int z = x; x = y; y = z - y * (a / b); return d; } ll x, y; int solve(ll m) { for (int i = 1; i <= n - 1; i++) for (int j = i + 1; j <= n; j++) { ll A = a[i].p - a[j].p, C = a[j].c - a[i].c, x, y, t = exgcd(A, m, x, y); if (C % t) continue; x = x * C / t; x = x % abs(m / t); if (x < 0) x += abs(m / t); if (x <= min(a[i].l, a[j].l)) return 0; } return 1; } int main () { //freopen("input.in", "r", stdin); //freopen("test.out", "w", stdout); ll maxn = 0; read(n); for (int i = 1; i <= n; i++) { read(a[i].c); read(a[i].p); read(a[i].l); maxn = max(maxn, a[i].c); } for (ll i = maxn; i <= 1000000; i++) { if (solve(i)) { printf("%lld\n", i); return 0; } } return 0 ; }
-
题型
e x g c d exgcd exgcd