题目描述:
对于一个序列,牛牛每次可以将序列中任意一个位置上的数乘上任意一个质数。
现在他想知道至少需要多少次操作才能使得该序列中的任意两个不同位置的数相乘都为完全平方数。
完全平方数:对于x,若其可以写成
i
×
i
=
x
i\times i = x
i×i=x的形式,则称x为完全平方数。
提示:一个数是完全平方数的充要条件是其所有质因子的指数都为偶数,例如
36
=
2
2
×
3
2
36 = 2^2\times 3^2
36=22×32
输入描述:
第一行输入一个整数N,表示序列长度
接下来一行输入N个整数,表示该序列
对于
100
%
100\%
100%的数据,
1
≤
N
≤
1
0
5
,
1
≤
序列中的数
≤
1
0
5
1\leq N\leq10^5,1\leq序列中的数\leq10^5
1≤N≤105,1≤序列中的数≤105
输入描述:
输出一个整数表示答案
示例1:
输入
3
2 1 2
输出
1
说明
只需要将第二个1乘上2即可,这样序列就变为2 2 2,任意两个数相乘都是4
示例2:
输入
3
2 4 6
输出
2
说明
将4乘上2,将6乘上3,序列变为2 8 18,任意两个数相乘都是完全平方数
思路:
分解质因数,统计每个因子在每个数中存在的个数为奇数还是偶数。只有偶数次则无需操作;有奇数次,则需判断时候有没有该因子的数,取小的进行操作;奇数偶数次都有,取小的进行操作。
AC代码:100%
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, x, res;
map<int, int> p1, p2;
void divide(int n)
{
for(int i=2;i<=n/i;i++)
if(n%i==0)
{
int s=0;
while(n%i==0)
{
n/=i;
s++;
}
if(s % 2) p1[i] ++;
else p2[i] ++;
}
if(n>1) p1[n] ++;
}
int main()
{
cin >> n;
for(int i = 0; i < n; i ++)
{
cin >> x;
divide(x);
}
for(int i = 0; i < 100002; i ++)
{
if(p1[i] != 0 && p1[i] < n) res += min(p1[i], n - p1[i]);
else if(p1[i] != 0 && p2[i] != 0) res += min(p1[i], p2[i]);
}
cout << res << endl;
return 0;
}