sdut3257(质因数分解平方和)

来源:互联网 发布:软件使用许可费 编辑:程序博客网 时间:2024/06/06 07:27
H - Square Number
Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%lld & %llu
SubmitStatusPracticeSDUT 3258
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