题目
一只青蛙想从河的一侧跳到另一侧。河中有一些石子,青蛙必须要经过这些石子才能够顺利过河。
由于青蛙一次跳过的距离是总是正整数,我们可以把河中青蛙可能到达的点看成数轴上的一串整点:
0
,
1
,
⋯
,
L
0,1,\cdots,L
0,1,⋯,L(其中
L
L
L 是河的宽度)。当青蛙的坐标大于
L
L
L 或者小于
0
0
0 时,我们就认为青蛙跳出了这条河。一旦青蛙跳出这条河,青蛙就不会选择回到河中。注意青蛙不一定最后要跳到河的另一侧。
现在,青蛙将会从
0
0
0 坐标开始,每次可以随意选择向正方向跳跃
a
a
a 步或者向负方向跳跃
b
b
b 步。
为了保障青蛙在河上的安全,你必须将所有青蛙可能跳到的坐标都铺上石子。
求使用的石子数量最少为多少?(
L
≤
1
0
12
,
a
,
b
≤
1
0
5
L \leq 10^{12}, a, b \leq 10^5
L≤1012,a,b≤105)
分析
如果不考虑河长的限制,答案就是 ⌊ L gcd ( a , b ) ⌋ \left\lfloor\frac{L}{\gcd(a, b)}\right\rfloor ⌊gcd(a,b)L⌋,考虑前 L − ( a + b ) L - (a + b) L−(a+b) 的部分显然是可以用上面的结论的,因为超出一个 a a a 或者 b b b 就能立刻再跳回来,然后最后的 a + b a + b a+b 格暴力即可。
代码
#include <bits/stdc++.h>
typedef long long LL;
const int MAXN = 100000;
LL L; int A, B;
inline int Gcd(const int &x, const int &y) {
return y ? Gcd(y, x % y) : x;
}
int Ans;
bool F[2 * MAXN + 5];
void Dfs(const int &u, const int &lim) {
F[u] = true, Ans++;
if (u + A <= lim && !F[u + A]) Dfs(u + A, lim);
if (u - B >= 0 && !F[u - B]) Dfs(u - B, lim);
}
int main() {
scanf("%lld%d%d", &L, &A, &B);
if (A + B >= L) {
Dfs(0, L);
printf("%d", Ans);
}
else {
Dfs(0, A + B);
printf("%lld", (L - A - B) / Gcd(A, B) + Ans);
}
return 0;
}