sdut3257(质因数分解平方和)

H - Square Number
Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%lld & %llu
use MathJax to parse formulas

Description

In mathematics, a square number is an integer that is the square of an integer. In other words, it is the product of some integer with itself. For example, 9 is a square number, since it can be written as 3 * 3.

Given an array of distinct integers (a1, a2, ..., an), you need to find the number of pairs (ai, aj) that satisfy (ai * aj) is a square number.

Input

The first line of the input contains an integer T (1 ≤ T ≤ 20) which means the number of test cases.

Then T lines follow, each line starts with a number N (1 ≤ N ≤ 100000), then N integers followed (all the integers are between 1 and 1000000).

Output

For each test case, you should output the answer of each case.

Sample Input

1   
5   
1 2 3 4 12

Sample Output

2
/*题意
   
   

一个整数,可以被表示为另一个整数的平方,这个整数称为平方数。

给你一个序列ai ~aj,规模为1e5,让你找出有多少对(ai,aj),使得ai×aj为平方数。

*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;

const int maxn = 1e6 + 10;
int isprime[maxn];
int prime[maxn];
int num[maxn];
int factor[maxn];    //该数组是将质因数分解后保存的某个因数的个数
int k = 0;

void init() //素数打表
{
    isprime[0] = 1;
    isprime[1] = 1;
    for(int i = 2; i < maxn; i++){
        if(!isprime[i]){
            prime[k++] = i;
            for(int j = 2*i; j < maxn; j += i){
                isprime[j] = 1;
            }
        }
    }
}

int main()
{
    init(); //素数打表
    int t;
    scanf("%d", &t);
    while(t--){
        memset(factor, 0, sizeof(factor));
        int n;
        scanf("%d", &n);
        long long ans = 0;
        for(int i = 0; i < n; i++)
            scanf("%d", &num[i]);
        for(int i = 0; i < n; i++){
            int temp = num[i];
            int remain = 1;
            for(int j = 0; j < k; j++){ //这里是不会超时的虽然k有可能很大但是接近1e6的值的个数n在10^2 ~ 10^3左右个自己可以手动算一下范围
                int times = 0;
                while(temp % prime[j] == 0){
                    temp /= prime[j];
                    times++;
                }
                if(times & 1){   //按位与对应二进制位都为1时当前位为1
                    remain *= prime[j]; //这里是保存上一个状态与当前的值(如:30 = 2 * 3 * 5)自己推一下看看必须是 *=
                }
                if(!isprime[temp] || temp == 1){
                    remain *= temp;
                    break;
                }
            }
             //ans += factor[remain]++;//可以合到一起但是如果该题试求立方和数下面两步就需要很清楚(见下一篇博客立方和数)
        ans += factor[remain];  //这一步是若出现一个remain可匹配数那么就有一个平方数
        factor[remain]++;      //这里是将出现过的需要匹配的数加加
        }
        printf("%lld\n", ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值