CF475D.CGCDSSQ(区间操作+map)

题目链接:https://vjudge.net/problem/CodeForces-475D
题意:给出n个数,和q个询问,每个询问给出x,要求回答有多少组[L,R]可以满足gcd(a[L],a[L+1],…,a[R])=x;
解题思路:
区间越大,gcd只会越来越小
为了简化复杂度,将相同的gcd区间保存在一起,直接跳过就可以
因为n的大小可以达到10^5,使用二维数组肯定不行,而且数值大小有10 ^9,使用一维数组也不行,所以使用map数组来保存gcd值对应的数量
m保存先前gcd值对应的区间数
next_m保存当前gcd值对应的区间数
从左向右,每遍历一个点更新一次m和next_m,然后将新得到的gcd组数加到result中

#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<map>
using namespace std;
map<int,int> m,next_m;
map<int,long long> result;
int n,q;
int a[110000];
int gcd(int a,int b){
	int tmp_a=max(a,b);
	int tmp_b=min(a,b);
	a=tmp_a;
	b=tmp_b;
	while(b){
		int tmp=b;
		b=a%b;
		a=tmp;
	}
	return a;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	cin>>q;
	for(int i=1;i<=n;i++){
		next_m.clear();
		map<int,int>::iterator it;
		for(it=m.begin();it!=m.end();it++){
			next_m[gcd(it->first,a[i])]+=it->second;
		}
		next_m[a[i]]++;
		swap(m,next_m);
		for(it=m.begin();it!=m.end();it++){
			result[it->first]+=it->second;
		}
	}
	while(q--){
		int tmp;
		scanf("%d",&tmp);
		printf("%lld\n",result[tmp]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/littlegoldgold/article/details/106785715