数列互质
一、题目及数据范围
题目描述
给出一个长度为n的序列,以及m组询问,求区间[li,ri]中有多少数在该区间中的出现次数与ki互质
数据范围
0<=n,m<=50000,0<=a[i]<=50000,0<=l,r,k<=50000
二、思考及解法
这道题很容易看出是莫队,我们考虑对每一个不同的k快速求出答案,由于a[i]的取值在[1,n],我们可以建一个桶cnt[i]来表示值为i的数出现的次数,但现在问题又来了,我们遍历cnt要O(n),然而这个时间太大,不好处理。
下一点就比较难想,由于我们只需要求出出现个数与k互质的个数,又1+2+…+x=x*(x+1)/2,所以出现个数的种类必然是根号n级别的,我们考虑再用一个桶times来记录出现个数的种数,这样我们可以遍历times数组并将符合条件的累加。
可是遍历times数组还是要花费O(n),考虑到值为0的times不用去管,我们可以用一个链表动态维护需要处理的times,times等于1时将下标加入链表,等于0时将之删除,这样就将时间复杂度降低到了O(n根号nlogn)。
代码实现
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAXN = 50005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*flag;
}
int n,m,block,a[MAXN],