CF 111B Petya and Divisors【想法题+二分(可省略)】

给出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;
	}
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值