1 条题解
-
0
自动搬运
来自洛谷,原作者为

saxiy
How can we rewrite the stars?搬运于
2025-08-24 21:42:05,当前版本为作者最后更新于2019-08-29 19:53:11,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
啊。。。本蒟蒻de了一下午的bug终于A了。。。
关于拓展欧几里得:
我们看到这种形式的表达式就会想起扩展欧几里得(如果你不会的话建议先A了P1082 同余方程这道题再来),这里介绍一种简单的写法
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; }很短吧,也很好理解,因为交换的同时我们交换了,所以原来辗转的方程被我们用引用简单地化解了。
题目分析:
这道题让我们求在一定限制下的解的个数,利用我们求出了一个特解,既然原来方程右边是,那我们两边都乘上就行了,即$x_{0}=x_{0}\times \frac{-c}{\gcd(a,b)},y_{0}=y_{0}\times \frac{-c}{\gcd(a,b)}$,然后我们现在有:
我们怎么得到原方程的通解呢?
先考虑在的情况下,在增加,必然会减小,要让增加一个整数的时候,刚好也需要减小一个整数,很明显,当增加时,减小,即:
但这不是最小的我们可以增加的那对整数,明显是那对最小的整数,而方程:
$$a(x_{0}+k\frac{b}{\gcd(a,b)})+b(y_{0}-k\frac{a}{\gcd(a,b)})=-c $$显然成立。所以我们原方程的解即为:
$$\begin{cases}x=x_{0}+k\frac{b}{\gcd(a,b)}\\y=y_{0}-k\frac{a}{\gcd(a,b)}\end{cases} $$现在我们来考虑的情况,将方程两边取反即可。
然后就是的情况,比如,我们可以设,那值域也要相应地取反,即
$$\begin{cases}x1^\prime=-x2\\x2^\prime=-x1\end{cases} $$然后,又转变成的情况了,时同理。
最后我们解出的取值范围,每一个都对应着一对可行解,输出可行的个数即可。
最后是特殊情况的总结:
- 时
- 时:
- 答案为所有的组合(乘法原理)
- 时:
- $y1 \leq y_{0} \leq y2 \Rightarrow ans=\text{x的所有可能}$
- 否则
- 时:与上同理
- 的解集为 时
代码实现(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; }网上复制粘贴谁不会啊
- 1
信息
- ID
- 1913
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者