codeforces 111B/112D Petya and Divisors

本文提供了一种高效解决CodeForces上题目111/B与112/D的方法。通过优化查找因数的方式及记录每个因数最后出现的位置来避免超时问题,附带详细的代码实现。

题目:Petya and Divisors
传送门:

http://codeforces.com/problemset/problem/111/B

http://codeforces.com/problemset/problem/112/D

分析:

  很容易想到读入x[i]、y[i],寻找x[i]的因数,判断一下是不是x[i-y[i]]、x[i-y[i]+1]...x[i-1]的某个数因数;但这样会超时;考虑以下两个优化:(1)寻找x[i]因数时循环范围只需要从j∈[0,sqrt(x[i])],但循环体内同时判断两个因数j、x[i]/j(注意当j*j==x[i]的情况);(2)把子问题“判断一下因数j是不是x[i-y[i]]、x[i-y[i]+1]...x[i-1]的某个因数”转变为问题“因数j最后一次位置出现在不在[i-y[i],i-1]”求解,并更新因数j最后一次位置。

代码:

#include<cstdio>
int n,last[100010];
int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    scanf("%d",&n);
    for(int i=1,x,y,ans;i<=n;++i){
        scanf("%d%d",&x,&y);
        ans=0;
        for(int j=1;j*j<=x;++j)
            if(x%j==0){
                if(last[j]<i-y)++ans;last[j]=i;
                if(j*j==x)continue;
                if(last[x/j]<i-y)++ans;last[x/j]=i;
            }
        printf("%d\n",ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/hjj1871984569/p/5281054.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值