Loading

abc 254 d 题解

abc 254 d

AT 链接

洛谷链接

题意

给定一个正整数 \(n\),请你求出有多少个数对满足一下条件:

  • \(1 \le i, j \le n\)

  • \(i \times j\) 是一个完全平方数。

\(1 \le n \le 2 \times 10 ^ 5\)

思路

暴力

枚举 \(i\)\(j\),判断乘积是否为完全平方数。

时间复杂度为 \(O(n ^ 2)\)

正解

对于每个 \(i \ (1 \le i \le n)\),令 \(f(i)\) 表示 \(i\) 最大的完全平方数因子。

也就是说,如果 \(i \times j\) 为完全平方数,就说明 \(\frac{i}{f(i)} = \frac{j}{f(j)}\)

因为 \(i \times j = f(i) \times f(j) \times \frac{i}{f(i)} \times \frac{j}{f(j)}\),而 \(f(i)\)\(f(j)\) 都是完全平方数,那么 \(\frac{i}{f(i)} \times \frac{j}{f(j)}\) 也必须是完全平方数,也就是 \(\frac{i}{f(i)} = \frac{j}{f(j)}\)

所以做法就是,记录所有 \(\frac{i}{f(i)}\) 出现的数量,再统计答案。

时间复杂度

如果用埃式筛预处理,那么时间复杂度为 \(O(n \times \log n)\)

如果直接循环找 \(f(i)\),那么时间复杂度为 \(O(n \times \sqrt n)\)

// 我的是 O(n * sqrt(n))
#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

int n, cnt[N];
long long ans;

int f(int i) {
  int s = 0;
  for (int j = 1; j * j <= i; j++) {
    if (i % j == 0) {
      int k = i / j;
      if (int(sqrt(j)) * int(sqrt(j)) == j) {
        s = max(s, j);
      }
      if (int(sqrt(k)) * int(sqrt(k)) == k) {
        s = max(s, k);
      }
    }
  }
  return s;
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cnt[i / f(i)]++;
  }
  for (int i = 1; i <= n; i++) {
    ans += cnt[i / f(i)];
  }
  cout << ans;
  return 0;
}
posted @ 2024-09-20 17:06  chengning0909  阅读(4)  评论(0编辑  收藏  举报