HDU 4611 Balls Rearrangement

令lcm=LCM(a,b),gcd=GCD(a,b)。cal(n,a,b)表示sum(abs(i%a-i%b)),0<=i<n。

显然,答案就是cal(lcm,a,b)*(n/lcm)+cal(n%lcm,a,b)。

cal(n,a,b)可以通过暴力得到,即对i%a和i%b的值分段,连续的一段(遇到0终止)可以直接得到值。

因此,每段的长度将直接影响到时间复杂度。

当lcm较小时,cal中的n不会很大,即使每段长度很小也无所谓。

当lcm较大时,每段的长度会比较大。

 1 #include<iostream>
 2 #include<algorithm>
 3 typedef long long LL;
 4 using namespace std;
 5 LL GCD(LL x, LL y) {
 6     return y ? GCD(y, x % y) : x;
 7 }
 8 LL LCM(LL x, LL y) {
 9     return x / GCD(x, y) * y;
10 }
11 LL cal(LL n, LL a, LL b) {
12     LL ans = 0;
13     LL x, y, tmp;
14     x = 0;
15     y = a;
16     for (LL i = a; i < n;) {
17         tmp = min(a - x, b - y);
18         if (i + tmp > n) {
19             tmp = n - i;
20         }
21         i += tmp;
22         ans += tmp * abs(x - y);
23         x = (x + tmp) % a;
24         y = (y + tmp) % b;
25     }
26     return ans;
27 }
28 int main() {
29     int T;
30     LL n, a, b;
31     LL lcm;
32     LL ans;
33     cin >> T;
34     while (T--) {
35         cin >> n >> a >> b;
36         if (a == b) {
37             ans = 0;
38         } else {
39             if (a > b) {
40                 swap(a, b);
41             }
42             lcm = LCM(a, b);
43             ans = (n / lcm) * cal(lcm, a, b) + cal(n % lcm, a, b);
44         }
45         cout << ans << endl;
46     }
47     return 0;
48 }
View Code

相关文章:

  • 2021-08-08
  • 2021-11-30
  • 2022-02-11
  • 2021-06-27
  • 2022-01-12
  • 2022-02-25
  • 2021-11-23
  • 2021-10-25
猜你喜欢
  • 2021-07-24
  • 2021-10-03
  • 2022-03-03
  • 2021-08-07
  • 2021-11-26
  • 2021-06-07
  • 2021-09-14
相关资源
相似解决方案