CF474F Ant colony

\(\texttt{Description}\)

CF474F

洛谷 CF474F

  • 给定 \(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}\)

Submission

$\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))));
	}
}
posted @ 2023-05-01 22:30  lzyqwq  阅读(33)  评论(0)    收藏  举报