Problem Description
In mathematics, a cube number is an integer that is the cube of an integer. In other words, it is the product of some integer with itself twice. For example, 27 is a cube number, since it can be written as 3 * 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 cube 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 9
Sample Output
2
题目描述
给n个数,求有多少组两个数的乘积是一个数的三次方.
解题思路
大致的思路就是将数 t 分解成若干个质因子相乘,忽略掉已经构成三次方的项,标记其中为二次方和一次方的项,然后统计与之互补的二次方和一次方的项的个数即为个数.
解法一
也是学习的博客上大多数的题解,是一个一个的枚举素数,将满足三次方的项消去,再分别统计二次方的项和一次方的项,这样写的不足就是一不小心就会写超时,搞得我魔改了很久.
解法二
from qq学姐 大体思路都是相同的,就是在处理时直接质因子分解,统计 t 是当前枚举质因子的几次方,然后将次数%3再接着统计.这样一来,便不需要每个数据都要遍历数据范围内所有的素数了,节省了很多时间.
代码实现
解法一
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false);\
cin.tie(0);\
cout.tie(0);
const int maxn = 1e6+7;
const int maxl = (int)sqrt(maxn+0.5);
bool vis[maxl];
int prime[maxl],num=0;
int mark[maxn];
void getprime()
{
for(int i=2;i<maxl;i++)
{
if(!vis[i])
{
prime[num++]=i;
for(int j=i*i;j<maxl;j+=i)
vis[j]=1;
}
}
}
int main()
{
IO;
getprime();
int T,n,t;
cin>>T;
while(T--)
{
cin>>n;
memset(mark,0,sizeof(mark));
ll ans=0;
for(int i=0;i<n;i++)
{
cin>>t;
ll x=1,y=1;
bool flag=true;
for(int j=0;prime[j]<=t&&j<num;j++)
{
int cube=prime[j]*prime[j]*prime[j];
while(t%cube==0) t/=cube;
if(t%(prime[j]*prime[j])==0)
{
t/=(prime[j]*prime[j]);
x=x*(prime[j]*prime[j]);
if(flag) y=y*prime[j];
}
else if(t%prime[j]==0)
{
t/=prime[j];
x=x*prime[j];
if(flag) y=y*prime[j]*prime[j];
}
if(y>maxn) flag=false;
}
if(flag)
{
y=y*t*t;
if(y<maxn) ans+=mark[y];
}
x=x*t;
mark[x]++;
}
cout<<ans<<endl;
}
return 0;
}
解法二
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IO ios::sync_with_stdio(false);\
cin.tie(0);\
cout.tie(0);
const int maxn = 1e6+7;
const int maxl = (int)sqrt(maxn+0.5);
bool vis[maxl];
int prime[maxl],num=0;
int mark[maxn];
ll ans;
void getprime()
{
for(int i=2;i<maxl;i++)
{
if(!vis[i])
{
prime[num++]=i;
for(int j=i*i;j<maxl;j+=i)
vis[j]=1;
}
}
}
void solve(int x)
{
vector<pair<int, int> > vc;
pair<int,int>pa;
for(int k=0;prime[k]*prime[k]<=x&&k<num;k++)
{
if(x%prime[k]==0)
{
pa=make_pair(prime[k],0);
while(x%prime[k]==0)
{
x/=prime[k];
pa.second++;
}
pa.second%=3;
if(pa.second!=0)
vc.push_back(pa);
}
}
if(x>1)
vc.push_back(make_pair(x,1));
int countt=1;
ll temp=1;
vector<pair<int,int> >::iterator it;
for(it=vc.begin();it!=vc.end();it++)
{
if((*it).second==1)
{
countt=countt*((*it).first);
temp=temp*((*it).first)*((*it).first);
}
else
{
countt=countt*((*it).first)*((*it).first);
temp=temp*((*it).first);
}
}
if(temp<maxn) ans+=mark[temp];
mark[countt]++;
}
int main()
{
IO;
getprime();
int T,n,t;
cin>>T;
while(T--)
{
cin>>n;
ans=0;
memset(mark,0,sizeof(mark));
for(int i=0;i<n;i++)
{
cin>>t;
solve(t);
}
cout<<ans<<endl;
}
return 0;
}