题解:CF2065G Skibidus and Capping
思路
可以先考虑一些性质:
-
半质数只有 2 种拆分方式,即为 1
\times 它自己,p \times q 。 -
发动我们惊人的注意力可以注意到,需要
由此进行分讨:
注意到,
看似结束了,实则还有一种。如:
AC code:
#include<bits/stdc++.h>
using namespace std;
long long _,n,a[200005],sum[200005],ji[200005],jib[200005],ck2[200005],ck[200005],ck3[200005];
inline bool CK(long long x){//是否为质数
for(long long i=2;i*i<=x;i++){
if(x%i==0)return 0;
}
return 1;
}
inline long long CK2(long long x){//是否为半质数
long long ans=0;
for(long long i=2;i*i<=x;i++){
if(x%i==0 && (ck[i]==0 || ck[x/i]==0))return -1;
}
return 1;
}
inline long long CK3(long long x){//若为半质数,它的q,p是多少
for(long long i=2;i*i<=x;i++){
if(x%i==0)return i;
}
return 0;
}
int main(){
for(long long i=1;i<=200000;i++)ck[i]=CK(i);
for(long long i=1;i<=200000;i++){
if(!ck[i])ck2[i]=CK2(i),ck3[i]=CK3(i);
}
scanf("%lld",&_);
while(_--){
long long ans=0;
scanf("%lld",&n);
for(long long i=1;i<=n;i++){
sum[i]=ji[i]=jib[i]=0;
scanf("%lld",&a[i]);
}
for(long long i=1;i<=n;i++){
if(ck[a[i]])ans+=(sum[i-1]-ji[a[i]]),ji[a[i]]++;//第一种分讨
sum[i]=sum[i-1]+ck[a[i]];
if(ck2[a[i]]==1)jib[a[i]]++,ans+=jib[a[i]];//第三种分讨
}
for(long long i=1;i<=n;i++){//第二种分讨
if(ck2[a[i]]==1){
long long t=ck3[a[i]];
ans+=ji[t]+ji[a[i]/t];
if(t*t==a[i])ans-=ji[t];
}
}
printf("%lld\n",ans);
}
}