https://atcoder.jp/contests/agc003/tasks/agc003_d
这题关键之处是想到3次方对应的3次方是唯一的,也就是说吧一个数质因数分解以后,吧每个因数的幂次都%3然后得到一个新数,那么这个新数只会和另一个确定的新数乘起来是三次幂
然后x^3<=10^20,x<=10^(20/3),那么对于每个数我们只要暴力枚举10^(10/3)内的质数就行了,筛完以后如果还剩,对于10^(10/3)到1e5中的质数,要么是x^2,要么是x,那么只要sqrt一下看是不是平方就行了
对于每一组相对的数字,选数量较多那边就行了
注意一个细节就是如果它本身就是个3次幂的话,处理出来就是1,然而1只能拿一个
(据说有人筛1e5以内的质数也过了,但我没卡过。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
const int up=4e3;
int n,m,cnt,tot,cas,ans;
ll a[maxl],b[maxl],c[maxl],p[maxl];
bool vis[maxl],no[maxl];
char s[maxl];
map<ll,int> mp;
inline void shai()
{
int t,j;
no[1]=true;
for(int i=2;i<=up;i++)
{
if(!no[i]) p[++p[0]]=i;
j=1;t=p[j]*i;
while(t<=up && j<=p[0])
{
no[t]=true;
if(i%p[j]==0)
break;
t=p[++j]*i;
}
}
}
inline void gank(ll x,int id)
{
b[id]=1;c[id]=1;
ll num;
for(int i=1;i<=p[0];i++)
if(x%p[i]==0)
{
num=0;
while(x%p[i]==0)
num++,x/=p[i];
num%=3;
if(num==1)
b[id]*=p[i],c[id]*=p[i]*p[i];
else if(num==2)
b[id]*=p[i]*p[i],c[id]*=p[i];
}
if(x!=1)
{
ll d=sqrt(x);
if(d*d==x)
b[id]*=d*d,c[id]*=d;
else
b[id]*=x,c[id]*=x*x;
}
}
inline void prework()
{
shai();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
gank(a[i],i);
mp[b[i]]++;
}
}
inline void mainwork()
{
for(int i=1;i<=n;i++)
if(mp[b[i]]>0)
{
if(b[i]==1)
++ans,mp[1]=0;
else
{
ans+=max(mp[b[i]],mp[c[i]]);
mp[b[i]]=mp[c[i]]=0;
}
}
}
inline void print()
{
printf("%d",ans);
}
int main()
{
int t=1;
//scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}