神奇的%系列二
Time Limit: 6000/3000 MS (Java/Others)
Memory Limit: 131070/65535 KB (Java/Others)
Problem Description
在计算机的世界里,%不是百分比,而是除法取余哟!
比如:
4 % 2 = 0
5 % 3 = 2
现在,给你N个正整数的序列,a[1],a[2]...a[i]...a[n]。
有 Q 个询问。
L R X ,问下标区间在[L,R]之间的数a[i],有几个数能整除X(即 X % a[i] == 0,且L<=i<=R)
Input
输入有多组数据,对于每组数据:(T<=25)
第一行:N(表示N个元素,1<=N<=100000)
第二行:a[1] a[2] ... a[n](表示序列的N个元素,1<=a[i]<=100000)
第三行:Q(表示Q个询问,1<=Q<=100000)
接下来Q行,每行三个整数:L R X(1<=L<=R<=N,1<=X<=100000)
Output
对于每个询问,输出一个数。
表示下标区间在[L,R]之间的数,有几个能整除X的数(即 X % a[i] == 0,且L<=i<=R)
Sample Input
5 1 2 3 4 5 3 2 4 6 1 5 2 1 5 60
Sample Output
2 2 5
查询[L,R]区间内X的约数个数,没有修改操作,所以可以用莫队,但没想到居然没TLE,而且速度还不错。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
using namespace std;
const int N=100005;
int n,m,a[N],ans[N],s[N],S,pos[N];
vector<int>v[N];
struct Q{
int l,r,val,id;
}q[N];
bool cmp(Q i,Q j){
return pos[i.l]<pos[j.l] || (pos[i.l]==pos[j.l] && i.r<j.r);
}
inline void init(){
for(int i=2;i<=N;i++){
for(int j=i;j<=N;j+=i){
v[j].push_back(i);
}
}
}
inline void add(int x,int val){
s[a[x]]+=val;
}
int main(){
init();
while(~scanf("%d",&n)){
S=(int)sqrt(n+0.5);
for(int i=1;i<=n;i++){
pos[i]=(i-1)/S;
scanf("%d",&a[i]);
}
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].val);
q[i].id=i;
}
memset(s,0,sizeof(s));
sort(q,q+m,cmp);
int l=1,r=0;
for(int i=0;i<m;i++){
if(r<q[i].r){
for(r=r+1;r<=q[i].r;r++){
add(r,1);
}
r--;
}
if(r>q[i].r){
for(;r>q[i].r;r--){
add(r,-1);
}
}
if(l>q[i].l){
for(l=l-1;l>=q[i].l;l--){
add(l,1);
}
l++;
}
if(l<q[i].l){
for(;l<q[i].l;l++){
add(l,-1);
}
}
ans[q[i].id]=s[1];
int si=v[q[i].val].size();
for(int j=0;j<si;j++){
ans[q[i].id]+=s[v[q[i].val][j]];
}
}
for(int i=0;i<m;i++){
printf("%d\n",ans[i]);
}
}
return 0;
}