试除法求约数O(sqrt(n))

  • 通过枚举较小的约数,并计算出成对的较大的约数

    1. vector<int> get_divisors(int n)
    2. {
    3. vector<int> res;
    4. for (int i = 1; i <= n / i; i ++) {
    5. if (n % i == 0) {
    6. res.push_back(i);
    7. if (i != n / i) {
    8. res.push_back(n / i);
    9. }
    10. }
    11. }
    12. sort(res.begin(), res.end());
    13. return res;
    14. }

    约数个数和约数之和

  • 把一个数进行质因子分解,约数 - 图1,对于每一项约数 - 图2,都有约数 - 图3种选择

  • 因此,约数个数为约数 - 图4
  • 因此,约数之和为约数 - 图5

    约数个数

    ```cpp

    include

    include

    using namespace std;

typedef long long LL; const int mod = 1e9 + 7;

int main() { int n; unordered_map hash; cin >> n; while (n —) { int x; cin >> x; // 质因子分解 for (int i = 2; i <= x / i; i ++) { while (x % i == 0) { hash[i] ++; x /= i; } } if (x > 1) { hash[x] ++; } } // 这个地方需要用long long,因为乘积可能溢出 LL ans = 1; for (auto kv: hash) { ans = ans * (kv.second + 1) % mod; } cout << ans << endl; return 0; }

  1. <a name="tbOTP"></a>
  2. #### [约数之和](https://www.acwing.com/problem/content/873/)
  3. ```cpp
  4. #include <iostream>
  5. #include <unordered_map>
  6. using namespace std;
  7. typedef long long LL;
  8. const int mod = 1e9 + 7;
  9. int main()
  10. {
  11. int n;
  12. unordered_map<int, int> hash;
  13. cin >> n;
  14. while (n --) {
  15. int x;
  16. cin >> x;
  17. for (int i = 2; i <= x / i; i ++) {
  18. while(x % i == 0) {
  19. hash[i] ++;
  20. x /= i;
  21. }
  22. }
  23. if (x > 1) {
  24. hash[x] ++;
  25. }
  26. }
  27. LL ans = 1;
  28. for (auto kv: hash) {
  29. int k = kv.first, v = kv.second;
  30. LL p = 1;
  31. for (int i = 0; i < v; i ++) {
  32. p = (p * k + 1) % mod;
  33. }
  34. ans = (ans * p) % mod;
  35. }
  36. cout << ans << endl;
  37. return 0;
  38. }

最大公约数

  • 根据约数的定义可知,如果d能整除a并且d能整除b,则d能整除(xa + yb)
  • 欧几里得定理gcd(a, b) == gcd(b, a % b)
  • 证明,a % b = a - (a / b) b,由于a, b均为整数,因此a / b为整数,因此a % b = a - c b
  • 对于a, b的公约数d,则d能整除a % b = a - c * b
  • 反之亦然,对于b, a % b的公约数d,d能整除a = a - c b + c b ```cpp

    include

    using namespace std;

int gcd(int a, int b) { return b ? gcd(b, a % b): a; }

int main() { int n; scanf(“%d”, &n); while (n —) { int a, b; scanf(“%d%d”, &a, &b); cout << gcd(a, b) << endl; } return 0; } ```