题意:
给出一个序列,然后又q个询问,每个询问给出[L,R],求区间中能整除X的数的个数。
题解:
这题类似于线段树,要求整除x的数的个数,其实就是求是X的因子的个数,我们首先打出1-maxn内的因子表。然后根据题目将L和R都向X连一条边,之后用离线操作统计区间[1,L],[1,R]因子的个数。具体做法看代码。
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const ll OO=0x3f3f3f3f3f3f3f3f;
const ll MOD=1000000007;
const int maxn = 100005;
int a[maxn];
vector<int>fac[maxn];
struct EDGE{
int v,id,next;
}E[maxn<<1];
int head[maxn<<1],tol;
int ans[maxn],num[maxn];
void get_fac(){
for(int i=1;i<maxn;i++)
for(int j=i;j<maxn;j+=i)
fac[j].push_back(i);
}
void Init(){
memset(head,-1,sizeof head);
tol=0;
}
void add_edge(int u,int v,int id){
E[tol].v=v;
E[tol].id=id;
E[tol].next=head[u];
head[u]=tol++;
}
int main(){
//freopen("G:\\read.txt","r",stdin);
int n,val,q,L,R,X;
get_fac();
while(scanf("%d",&n)!=EOF){
Init();
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d %d %d",&L,&R,&X);
add_edge(L-1,X,i);
add_edge(R,X,i);
ans[i]=-1;
}
memset(num,0,sizeof num);
for(int i=1;i<=n;i++){
num[a[i]]++;
for(int j=head[i];j!=-1;j=E[j].next){
int v=E[j].v,id=E[j].id,SIZE=fac[v].size();
int res=0;
for(int k=0;k<SIZE;k++)
res+=num[fac[v][k]];
if(ans[id]!=-1) ans[id]=res-ans[id];
else ans[id]=res;
}
}
for(int i=1;i<=q;i++)
printf("%d\n",ans[i]);
}
return 0;
}