题目链接
做的时候觉得如果要查看两个数的乘积是不是平方数,就必须把每个数字与另外的每一个数字比较,也就是有O(N^2)的复杂度。谁知道一看题解,竟然用到了数学的知识。每一个平方数都可以表示成为多个素数的偶次幂的乘积。这个其实是应用了唯一分解定理。唯一分解定理是说:任何大于1的自然数都可以唯一的用若干个素数的乘积表示出来。那么一个平方数自然就可以表示成为若干个素数的偶次幂的乘积了。然后我们就可以运用这个做题了。把每个数字化简到最简的数字,然后就可以得到答案了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <iostream> #include <stdio.h> #include <algorithm> #include <cstring> #include <string> using namespace std; bool vis[1001000]; int prime[1001000]; int flag[1001000]; int tot; int prim() { tot = 0; memset(vis,0,sizeof(vis)); for(int i = 2; i <= 1000001; ++i) { if(!vis[i]) { prime[++tot] = i * i; for(int j = i + i; j <= 1000001; j += i) { vis[j] = 1; } } } } int main() { prim(); int t, n, num; cin >> t; while(t--) { memset(flag,0,sizeof(flag)); scanf("%d",&n); for(int i = 1; i <= n; ++i) { cin >> num; for(int j = 1; j <= tot && prime[j] <= num; ++j) { while(num % prime[j] == 0) { num /= prime[j]; } } flag[num]++; } long long ans = 0; for(int j = 1; j <= 1000010; ++j) { ans += flag[j] * (flag[j] - 1) / 2; } cout << ans << '\n'; } }
|