题解:CF2065G Skibidus and Capping
Magallan_forever · · 题解
简要说明题意:
定义满足
题目分析:
注意到符合条件的只有这三种情况:
-
-
-
第三种情况是
a_i=a_j ,a_i 是半质数。
如果
如果
如果
那么就比较好做了,预处理所有的质数,在读入时根据
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
vector<int> p;
int markp[200001];
bool semip[200001];
void euler(){
for(int i=2;i<=200000;++i){
if(!markp[i]) markp[i]=i,p.push_back(i);
for(int j=0;j<p.size()&&(long long)p[j]*i<=200000&&p[j]<=markp[i];++j){
markp[p[j]*i]=p[j];
if(markp[i]==i) semip[p[j]*i]=true;
}
}
}
int C[200001],n,mark[200001],cntp[200001];//C是权值树状数组,mark用于统计质数和半质数,cntp[i]是已经出现的含i的半质数个数
int lowbit(int v){
return v&(-v);
}
void modify(int x,int v){
for(;x<=n;x+=lowbit(x)) C[x]+=v;
}
int query(int l,int r){ //[l,r]
int cnt=0;
for(--l;l;l-=lowbit(l)) cnt-=C[l];
for(;r;r-=lowbit(r)) cnt+=C[r];
return cnt;
}
int main(){
int T;
long long cnt;//这答案肯定会爆int
scanf("%d",&T),euler();
while(T--){
scanf("%d",&n),fill(C+1,C+1+n,0),fill(mark+1,mark+1+n,0),fill(cntp+1,cntp+1+n,0),cnt=0ll;
for(int i=0,temp;i<n;++i){
scanf("%d",&temp);
if(markp[temp]==temp) ++mark[temp],modify(temp,1),cnt+=query(1,temp-1)+query(temp+1,n)+cntp[temp];
if(semip[temp]){
++mark[temp],++cntp[markp[temp]],cnt+=mark[markp[temp]]+mark[temp];
if(markp[temp]^(temp/markp[temp])) cnt+=mark[temp/markp[temp]],++cntp[temp/markp[temp]];
}
}
printf("%lld\n",cnt);
}
return 0;
}