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;
}

posted @ 2022-06-05 12:03  qingyanng  阅读(51)  评论(0编辑  收藏  举报