题意:求n个数中乘积是立方数的数的对数。
n<=
105
,a[i]<=
106
解法:
将每个数分解质因子。求得每个<1000的质因子模3的幂次
(若两个数乘积是立方数,则该立方数的每个质因子必定小于1000),得到每个数
质因子模3幂次
的乘积,以及
质因子3−模3幂次
的乘积。只需要统计后面这个数的出现的次数,就可以知道该数*某数是立方数的个数。
该解法可能并非正解,刚好卡着时限过题。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#define ll long long
using namespace std;
const int maxn = 100000+10;
int t,n;
int x;
bool not_prime[maxn];
int a[maxn];
int prime[maxn],num;
map<ll,int> ma;
ll tmpa,tmpfan;
ll tmp[maxn],tmpf[maxn];
int cnt;
ll ans;
void init(){
num=0;
for(int i=2;i<=1000;i++){
if(!not_prime[i]) prime[num++]=i;
for(int j=0;j<num&&i*prime[j]<=1000;j++){
not_prime[i*prime[j]]=1;
if(!(i%prime[j])) break;
}
}
}
ll Power(int a,int b){
if(b==1) return (ll)a;
if(b==2) return (ll)a*a;
}
bool factor(int x){
tmpa=1,tmpfan=1;
for(int i=0;i<num&&prime[i]*prime[i]<=x;i++){
int tmp;
if(x%prime[i]==0){
tmp=0;
while(x%prime[i]==0){
tmp++;
if(tmp%3==0) tmp=0;
x/=prime[i];
}
if(tmp!=0){
tmpa=tmpa*Power(prime[i],tmp);
tmpfan=tmpfan*Power(prime[i],3-tmp);
}
}
}
if(x>1000) return 0;
else{
tmpa=tmpa*(ll)Power(x,1);
tmpfan=tmpfan*(ll)Power(x,2);
return 1;
}
}
int main(){
//freopen("a.txt","r",stdin);
scanf("%d",&t);
init();
while(t--){
ma.clear();
ans=0;
scanf("%d",&n);
cnt=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(factor(a[i])){
tmp[cnt]=tmpa;
tmpf[cnt++]=tmpfan;
}
}
for(int i=0;i<cnt;i++){
ans+=ma[tmpf[i]];
ma[tmp[i]]++;
}
printf("%lld\n",ans);
}
return 0;
}