题意:
给出一个序列,然后又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; }