题解 P2833 【等式】
啊。。。本蒟蒻de了一下午的bug终于A了。。。
关于拓展欧几里得:
我们看到
void exgcd(ll a, ll b, ll &x, ll &y, ll &gcd) {
if(!b) { x = 1; y = 0; gcd = a; return; }
exgcd(b, a % b, y, x, gcd); y -= a / b * x;
}
很短吧,也很好理解,因为交换
题目分析:
这道题让我们求
我们怎么得到原方程的通解呢?
先考虑在
但这不是最小的我们可以增加的那对整数,明显
显然成立。所以我们原方程的解即为:
现在我们来考虑
然后就是
然后
最后我们解出
最后是特殊情况的总结:
-
x1>x2\text{或}y1>y2$ 时 $ans=0 -
> - $c=0$ 答案为$x,y$所有的组合(乘法原理) > - $c\neq 0 \Rightarrow ans=0 -
> - $y1 \leq y_{0} \leq y2 \Rightarrow ans=\text{x的所有可能} - 否则
ans=0
- 否则
-
-
c\bmod\gcd(a,b)\ne 0 \Rightarrow ans=0 -
k$的解集为$\emptyset$ 时 $ans=0
代码实现(50ms):
#pragma GCC optimize("fast-math")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a, b, c, _x1, _x2, _y1, _y2;
void exgcd(ll a, ll b, ll &x, ll &y, ll &gcd) {
if(!b) { x = 1; y = 0; gcd = a; return; }
exgcd(b, a % b, y, x, gcd); y -= a / b * x;
}
void ans(ll val) { printf("%lld", val); exit(1); }
int main() {
scanf("%lld%lld%lld%lld%lld%lld%lld",
&a, &b, &c, &_x1, &_x2, &_y1, &_y2);
if(_x1 > _x2 || _y1 > _y2) ans(0);
c = -c;//移项
if(!a && !b) {
if(c) ans(0);
else ans((_x2 - _x1 + 1) * (_y2 - _y1 + 1));
}
if(a < 0 && b < 0) a = -a, b = -b, c = -c;
else if(a < 0) swap(_x1, _x2), _x1 = -_x1, _x2 = -_x2, a = -a;
else if(b < 0) swap(_y1, _y2), _y1 = -_y1, _y2 = -_y2, b = -b;
ll x, y, gcd;
exgcd(a, b, x, y, gcd);
if(c % gcd) ans(0);
c /= gcd; x *= c; y *= c;
if(!a) (_y1 <= y && y <= _y2) ? ans(_x2 - _x1 + 1) : ans(0);
if(!b) (_x1 <= x && x <= _x2) ? ans(_y2 - _y1 + 1) : ans(0);
double l = double(gcd * (_x1 - x)) / b;//x范围定界
double r = double(gcd * (_x2 - x)) / b;
l = fmax(l, double(gcd * (y - _y2)) / a);//y范围定界
r = fmin(r, double(gcd * (y - _y1)) / a);
int ansl = ceil(l), ansr = floor(r);//注意边界取整
ans(ansr >= ansl ? ansr - ansl + 1 : 0);
return 0;
}
网上复制粘贴谁不会啊