1. 程式人生 > >Codeforces - 773A - Success Rate - 二分

Codeforces - 773A - Success Rate - 二分

div ring using out force fin code include 增量

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的時候。

Codeforces - 773A - Success Rate - 二分