AT_abc408_g [ABC408G] A/B < p/q < C/D 题解
其实这是一道原题,详情见 P5179。
首先看到这道题的第一眼,一般都是二分吧……那么我们来想一下:
它要求
但是,这是错的。你可以试试第一组数据下
原因很简单,左边界为上取整,如果它正好比
那么怎么做呢?首先你需要发现如果要求
如果学过类欧的话,应该不难想到类欧的策略。如果不会也没关系,不影响我们的推导。
首先我们先考虑边界情况
然后我们就想通过多次变换,使得
这里有一个很巧妙的思路:将我们的
为什么这个是对的呢?那么我们要证明当要求
考虑反证法,假设我们让分母更小时,分子要变大。那么我们应当存在另一个符合条件的分数
或者我们让分子更小时,分母要变大。那么我们应当存在另一个符合条件的分数
这两个假设与结论均矛盾,所以我们让分母(或分子)变小时,分子(或分母)也会变小。证毕。
代码如下:
#include<bits/stdc++.h>
#define int long long
using namespace std;
void cal(int a,int b,int c,int d,int &A,int &B){
if(a<b&&c>d){
A=B=1;
return;
}
cal(d%c,c,b-(d/c)*a,a,B,A);// d-(d/c)*c=d%c
B+=(d/c)*A;
return;
}
int a,b,c,d,A,B;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T=1;
cin>>T;
while(T--){
cin>>a>>b>>c>>d;
A=B=0;
cal(a,b,c,d,A,B);
cout<<B<<"\n";
}
return 0;
}
但是这样做复杂度真的优秀吗?你可以根据代码,这么感性理解:首先考虑 d%c,c),然后第二轮我们不管,然后第三轮再次被辗转相除了一下……这其实就是求最大公约数的思路!不难得出辗转相除法的复杂度为