Loading

abc 253 题解

D - FizzBuzz Sum Hard

记得戳题目哦

题目大意:

请找出从 \(1\)\(N\) 中不为 \(A\)\(B\) 的倍数的数之和。

题解

我们知道,\(A\)\(1\) 倍是 \(A \times 1\), \(A\)\(2\) 倍是 \(A \times 2\), \(A\)\(3\) 倍是 \(A \times 3\), 以此类推。
所以在 \(1\)\(N\) 之间 \(A\) 的倍数的和为:\(A \times 1\) + \(A \times2\) + ...... + \(A \times (N \div A)\),提取公因数后为:\(A \times (1 + 2 + ...... + N \div A)\),可简化为:\(A \times (N \div A) \times (N \div A + 1) \div 2\)

\(B\) 同上。

但是,有的数既是 \(A\) 的倍数,又是 \(B\) 的倍数,所以得把\(A\)\(B\) 的公倍数排除出来,算法同上。

介绍一下 \(O(\log n)\) 求最大公因数和最小公倍数的算法

欧几里得算法:

gcd:最大公因数, \(\gcd(a, b) = \gcd(b, a \mod b)\)

lcm:最小公倍数, \(lcm(a, b) = a \times b \div \gcd(a, b)\)

最小公倍数的代码也贴一下吧(欧几里得算法):

long long gcd(long long a, long long b) {   // 最大公因数
  if (a % b == 0) {
    return b;
  } else {
    return gcd(b, a % b);
  }
}
long long lcm(long long a, long long b) {   // 最小公倍数
  return a * b / gcd(a, b);
}


最后贴个代码

#include <iostream>

using namespace std;

long long n, a, b, ans;

long long gcd(long long a, long long b) {
  if (a % b == 0) {
    return b;
  } else {
    return gcd(b, a % b);
  }
}
long long lcm(long long a, long long b) {
  return a * b / gcd(a, b);
}

int main() {
  cin >> n >> a >> b;
  long long ans_1 = n / a, ans_2 = n / b, ans_3 = n / lcm(a, b);
  ans = (1 + n) * n / 2;
  long long sum1 = a * (1 + ans_1) * ans_1 / 2;
  long long sum2 = b * (1 + ans_2) * ans_2 / 2;
  if (lcm(a, b) <= n) {
    long long sum3 = lcm(a, b)  * (1 + ans_3) * ans_3 / 2;
    ans = ans - sum1 - sum2 + sum3;
  } else {
    ans = ans - sum1 - sum2;
  }
  cout << ans;
  return 0;
}

不喜勿喷,谢谢

posted @ 2023-02-28 21:33  chengning0909  阅读(41)  评论(0编辑  收藏  举报