两个闹钟
两个闹钟
有两个闹钟。
第一个闹钟会在 $b,b+a,b+2a,b+3a, \dots$ 时刻响铃。
第二个闹钟会在 $d,d+c,d+2c,d+3c, \dots$ 时刻响铃。
请计算两个闹钟第一次同时响铃的具体时刻。
输入格式
第一行包含两个整数 $a,b$。
第二行包含两个整数 $c,d$。
输出格式
一个整数,表示第一次同时响铃的具体时刻。
如果永远都不可能同时响铃,则输出 $−1$。
数据范围
所有测试点满足 $1 \leq a,b,c,d \leq 100$。
输入样例1:
20 2 9 19
输出样例1:
82
输入样例2:
2 1 16 12
输出样例2:
-1
解题思路
我们是直接枚举答案。假设有$b + x \cdot a + d + y \cdot c = t$,那么$t$一定满足$t \geq b, t \geq d$,同时还要满足$a \mid t - b, c \mid t - d$。
我们的$t$一开始的取值就要比$b$和$d$都要大。
然后,我们要满足$a \mid t - b$,我们只用关心$t - b$除以$a$的余数是多少,可以发现$t - b - k \cdot a$除以$a$的余数没有改变,不会影响余数。同理$t - d - k \cdot c$也不会影响余数。因此,我们从将$t - b$和$t - d$同时减去$a$和$c$的最小公倍数,也不会改变余数$t - b - k \cdot lcm \left( {a, c} \right)$,$t - d - k \cdot lcm \left( {a, c} \right)$,因此我们只需要考虑$t - b$和$t - d$在$lcm \left( {a, c} \right)$以内的数就可以了。因为如果大于$lcm \left( {a, c} \right)$的话,那么我们就减去$lcm \left( {a, c} \right)$,并不会影响余数。因为$a$和$c$的值在$100$以内,所以最小公倍数在$10000$以内。又因为$b$和$d$最大是$100$,因此$t$枚举到$10100$就可以了。
AC代码如下:
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 int main() { 6 int a, b, c, d; 7 scanf("%d %d %d %d", &a, &b, &c, &d); 8 9 for (int i = max(b ,d); i <= 10100; i++) { 10 if ((i - b) % a == 0 && (i - d) % c == 0) { 11 printf("%d", i); 12 return 0; 13 } 14 } 15 16 printf("-1"); 17 18 return 0; 19 }
还可以用扩展欧几里得。由$b + a \cdot x = d + c \cdot y$,得到$a \cdot x - c \cdot y = d - b$。如果$gcd \left( {a, c} \right) \mid d - b$,才有解。先让$x$取到最小正整数,然后通过式子求得$y$,当$y < 0$,那么$x$和$y$同时加上对应的值。
AC代码如下:
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 int exgcd(int a, int b, int &x, int &y) { 6 if (b == 0) { 7 x = 1, y = 0; 8 return a; 9 } 10 11 int d = exgcd(b, a % b, y, x); 12 y -= a / b * x; 13 14 return d; 15 } 16 17 int main() { 18 int a, b, c, d, x, y; 19 scanf("%d %d %d %d", &a, &b, &c, &d); 20 21 int gcd = exgcd(a, c, x, y); 22 if ((d - b) % gcd) { 23 printf("-1"); 24 } 25 else { 26 x *= (d - b) / gcd; 27 int tx = c / gcd, ty = a / gcd; 28 x = (x % tx + tx) % tx; 29 y = (b + a * x - d) / c; 30 while (y < 0) { 31 x += tx; 32 y += ty; 33 } 34 35 printf("%d", b + a * x); 36 } 37 38 return 0; 39 }
参考资料
AcWing 4379. 两个闹钟(AcWing杯 - 全国联赛):https://www.acwing.com/video/3755/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16074352.html