CF474F Ant colony
\(\texttt{Description}\)
给定 \(a_1\sim a_n\) 和 \(q\) 组询问,每次询问 \(a_l\sim a_r\) 之间,不能整除区间内所有数的数的个数。
\(n,q\le 10^5\),\(a_i\le 10^9\)。
\(\texttt{Solution}\)
首先补集转化为能整除区间内所有数的数的个数。考虑怎样的数满足性质。
如果一个数 \(x\) 不在区间内并且能整除区间内的所有数,说明 \(x|\gcd\limits_{i=l}^ra_i\)。现在这个数在区间内,说明它既是 \(\gcd\) 的倍数,又是 \(\gcd\) 的约数,显然 \(x=\gcd\limits_{i=l}^ra_i\)。问题转化为求区间内 \(\gcd\) 的个数。用 ST 表维护 \(\gcd\),用树状数组套 unordered_map 维护区间内某个数的个数。
时间复杂度为 \(\mathcal{O}(n\log^2n)\),空间复杂度为 \(\mathcal{O}(n\log n)\),可以接受。
\(\texttt{Code}\)
$\texttt{Click for Code}$
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,g[20][N],lg[N];
unordered_map<int,int>bit[N];
int gcd(int l,int r){
int k=lg[r-l+1];
return __gcd(g[k][l],g[k][r-(1<<k)+1]);
}
void modify(int x,int k){
for(int i=x;i<=n;i+=i&(-i)){
++bit[i][k];
}
}
int query(int x,int k){
int ret=0;
for(int i=x;i;i-=i&(-i)){
if(bit[i].find(k)!=bit[i].end()){
ret+=bit[i][k];
}
}
return ret;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
lg[i]=log2(i);
scanf("%d",&g[0][i]);
modify(i,g[0][i]);
}
for(int i=1;i<=lg[n];++i){
for(int j=1;j+(1<<i)-1<=n;++j){
g[i][j]=__gcd(g[i-1][j],g[i-1][j+(1<<(i-1))]);
}
}
scanf("%d",&m);
for(int i=1,l,r;i<=m;++i){
scanf("%d%d",&l,&r);
printf("%d\n",r-l+1-(query(r,gcd(l,r))-query(l-1,gcd(l,r))));
}
}

浙公网安备 33010602011771号