[CSP-S模拟测试]:平方数(数学+哈希)

题目传送门(内部题137)


输入格式

  第一行,一个正整数$n$。
  第二行$n$个正整数$a_1\sim a_n$。


输出格式

  输出一个整数,为满足条件的二元组个数。


样例

样例输入:

5
1 2 3 4 12

样例输出:

2


数据范围与提示

  对于$20\%$的数据,满足$n\leqslant 3,000$。
  对于$50\%$的数据,满足$n\leqslant 50,000$。
  对于另$20\%$的数据,满足$a_i\leqslant 1,000$。
  对于$100\%$的数据,满足$1\leqslant n\leqslant 300,000,1\leqslant a_i\leqslant 10^9$。


题解

两个数相乘为平方数即其在分解质因数后奇数次的数相同。

这个可以用哈希维护,用$unordered\text{_}map$记录一下就好了。

质数比较多,但是我们可以只利用前几个质数就好了。

时间复杂度:$\Theta(kn)$($k$为利用的质数的个数)。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int>mp;
int n;
int pri[170],cnt;
bool vis[1000];
long long ans;
void pre_work()
{
	for(int i=2;i<1000;i++)
	{
		if(vis[i])continue;pri[++cnt]=i;
		for(int j=i;j<1000;j+=i)vis[j]=1;
	}
}
int main()
{
	pre_work();
	scanf("%d",&n);
	while(n--)
	{
		int x,res=1;
		scanf("%d",&x);
		for(int i=1;i<=cnt;i++)
		{
			while(!(x%(pri[i]*pri[i])))x/=pri[i]*pri[i];
			if(!(x%pri[i])){x/=pri[i];res*=pri[i];}
		}
		if((int)(sqrt(x))*(int)(sqrt(x))!=x)res*=x;
		ans+=mp[res];mp[res]++;
	}
	printf("%lld",ans);
	return 0;
}

rp++

posted @ 2019-11-10 14:50  HEOI-动动  阅读(166)  评论(0编辑  收藏  举报