Codeforces - 773A - Success Rate - 二分 - 简单数论

https://codeforces.com/problemset/problem/773/A

一开始二分枚举d,使得(x+d)/(y+d)>=p/q&&x/(y+d)<=p/q,错在这些数是离散的,不能由两边异号判定一定存在这个交点。

然后改成枚举d,使得y=d*q,这样就一定是倍数了。然后就是要想清楚了,找不到这样卡在中间的d,其实都是因为d不够大的原因,d够大保证是可以的除非正确率是100%。

然后就是二分的上界,按道理q的最大值是1e9,y的最大值也是1e9,他们的公倍数肯定在1e18范围内(p和q任意组合能得到的比值最多就是1e18/2,把1e18都枚举完肯定能遍历所有能构造出的情况),那么最大值肯定是1e18/q,多个1都不行。

 

二分,老朋友了,while(1),当l==m的时候是边界,特判就好。

#include<bits/stdc++.h>
using namespace std;
#define ll long long

string a,b;
string c;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        ll x,y,p,q;
        scanf("%lld%lld%lld%lld",&x,&y,&p,&q);
        ll l=1,r=1e18/q,m;
        ll ans;
        while(1){
            m=(l+r)>>1;
            //cout<<l<<" " <<r<<" "<<m<<endl;

            if(l==m){
                ll del=l*q-y;
                if(del>=0&&(x+del)>=l*p&&x<=l*p){
                    ans=l;
                }
                else if((r*q-y)>=0&&(x+(r*q-y))>=r*p&&x<=r*p){
                    ans=r;
                }
                else{
                    ans=-1;
                }
                break;
            }
            if(m*q<y){
                l=m+1;
                continue;
            }
            ll del=m*q-y;
            if((x+del)>=m*p&&x<=m*p){
                r=m;
                //cout<<m<<" ok"<<endl;
            }
            else{
                l=m+1;
            }
        }

        printf("%lld\n",ans==-1?-1:ans*q-y);

    }
}

 其实还有直接用公式解的方法,设最终的状态为pt/qt,只要保证增量为正数即可,当然是pt>=x,qt>=y,还有错的题不会再变对,qt-pt>=y-x,三个式子直接解出来。

这个方法要注意特判p==q的情况,这种时候不能作除法,还有p==0和q==0的时候。

转载于:https://www.cnblogs.com/Yinku/p/10414473.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值