给出n对询问
每对询问类似
x,y
对该个询问,是这个x的约数却不是上面y个x的约数的约数个数是多少
很容易想出
我们用一个二维数组来维护
G[i]里面里面存的是含有约数i的位置有那些(由于从上到下来扫并更新G,这个G[i]肯定是单增的)
那么对当前的一个询问x,y, 当前位置为i
我们一个一个的得到x的约数,对每个约数m,
看G[m]里面记录的位置有没有[i-y-1,i-1]中的数,如果有的话,这个约数就不是,否则就是
这有很多方法, 可以二分查找i-y-1和i,根据返回的下标进行逻辑分析
平妈的改进
直接看最后一个即可
因为这串数是递增的,而且最后一个数肯定严格小于i(当前位置),那么只要看最后一个数是不是严格小于i-y-1就是了
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define pb push_back
vector<int > G[111111];
vector<int > pos[111111];
int main(){
#ifndef ONLINE_JUDGE
freopen("G:/in.txt","r",stdin);
//freopen("G:/myout.txt","w",stdout);
#endif
int n;
cin>>n;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
int cnt=0;
for(int j=1;j*j<=x;j++){
if(x%j==0){
for(int t=1;t<=1+(j*j!=x);t++){
int div;
t==1?div=j:div=x/j;
int index1=lower_bound(pos[div].begin(),pos[div].end(),i-y-1)-pos[div].begin();
int index2=lower_bound(pos[div].begin(),pos[div].end(),i)-pos[div].begin();
if(index1+1>=index2){
bool ok=true;
if(index1<pos[div].size()){
if(pos[div][index1]>=i-y && pos[div][index1]<=i-1)
ok=false;
}
if(ok)
cnt++;
}
pos[div].pb(i);
}
}
}
cout<<cnt<<endl;
}
}