AtCoder Beginner Contest 254 D (数学,平方数性质)
题意: 求小于等于N的i,j 使得i * j为平方数
题解: 定义fi为i的最大平方数因子,i * j 要想是平方数, i / fi * j / fj 也要是平方数,fi去掉最大平方因子后,i/fi一定是只出现一次的质数的乘积,所以 i * j 要想是平方数必有 i / fi = j / fj 。
nlogn求出每个数的所有因子,答案就是 cnt[i / fi] ^ 2
#include<bits/stdc++.h>
//#include <bits/extc++.h>
using namespace std;
// using namespace __gnu_cxx;
// using namespace __gnu_pbds;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define ull unsigned long long
#define li __int128_t
#define PII pair<int, int>
#define re register
//#define int long long
const int N = 2e5 + 5;
const int M = 1e6 + 5;
const int mod = 1e9 + 7;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
int cnt[N]; bool sq[N];
int main() {
int n; cin >> n;
vector<vector<int>> ve(n + 1);
for ( int i = 1; i * i <= n; ++ i ) {
sq[i * i] = 1;
}
for ( int i = 1; i <= n; ++ i ) {
for ( int j = i; j <= n; j += i ) {
ve[j].push_back(i);
}
}
for ( int i = 1; i <= n; ++ i ) {
int f = 1;
for ( auto j : ve[i] ) if( sq[j] ) f = j;
++ cnt[i / f];
}
ll ans = 0;
for ( int i = 1; i <= n; ++ i ) {
ans += cnt[i] * cnt[i];
}
cout << ans << '\n';
return 0;
}