AtCoder Beginner Contest 342

D.Square Pair

给你一个数组,最多2e5个元素,每个元素的范围是0到2e5
问选出两个元素,乘积为完全平方数的情况有多少?(任选a[i] a[j],且满足i < j)

一种思路是用map记录数组的元素,选出一个元素 x 后,枚举所有完全平方数,如果完全平方数可以整除选出的这个元素且整除的结果 y 在map中,那就满足题意,只需要保证让x < y 就可以避免重复计数.但是这样时间复杂度太高了.

注意到这个元素如果他的因子是完全平方数,那么这个因子对最终乘以另一个数是否为完全平方数并不会造成影响.可以直接把这个因子去掉.最终剩下的因子都是奇数次方.那当且仅当一个数奇数次的因子与挑选出的另一个数的奇数次因子完全一样就能构成完全平方数了.而我们不需要真的挨个判断因子,只需要判断因子的乘积就可以了.(为了避免其他情况,我们只挑选质因子.并且根据唯一分解定理).

最后统计计数就可以了.注意 0 也要算.

#include<bits/stdc++.h>

using namespace std;

#define int long long

void solve()
{
    int n;
    cin>>n;
    vector<int>a(n);
    map<int,int>m;
    int res = 0;

    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        
        for(int j=2;j<=a[i]/j;j++)
        {
            while(a[i]%(j*j)==0)
            {
                a[i]/=(j*j);
            }
        } 
        // cout<<a[i]<<' ';
        m[a[i]]++;
    }    
    for(auto[x,y]:m)
    {
        if(!x)
        {
            // res+=n-y;
            continue;
        }
        else
        {
            res+=m[0]*y;
            res+=y*(y-1)/2;
        }
    }
    res+=m[0]*(m[0]-1)/2;
    cout<<res;
}

signed main()
{
    int T = 1;
    // cin>>T;

    while(T--)
        solve();

    return 0;
}
posted @ 2024-02-26 12:43  LZH_03  阅读(14)  评论(0编辑  收藏  举报