题解:abc408_g

题解:abc408_g

link

首先我们考虑简化一下问题,当 \(\frac AB\ge1\) 的时候,将 \(\frac AB\)\(\frac CD\) 都减去 \(\lfloor\frac AB\rfloor\),最后再给 \(\frac pq\)\(\lfloor\frac AB\rfloor\)

否则我们考虑 \(\frac AB<1\) 的情况,由于 \(\frac AB<\frac pq<\frac CD\) 中的数都是正整数,所以显然可以转化为 \(\frac DC<\frac qp<\frac BA\),这启发我们不只是求最小的 \(q\),而是同时求解 \(p\)\(q\)

我们在 \(\frac CD\le1\) 的时候这样转化可以保证复杂度,因为 \((C,D)\) 首先会变成 \((D,C)\),然后因为 \(D\ge C\),同减 \(\lfloor\frac CD\rfloor\) 后又会变成 \((D\mod C,C)\),这个过程类似递归求 \(\gcd\),可以证明其复杂度为 \(O(\log\max\{A,B,C,D\})\)

而在 \(\frac AB<1<\frac CD\) 的时候,直接返回 \(p=1,q=1\) 即可,这样显然是最优的。

但为了保证正确性,我们还需要一个性质,即当 \(\frac CD\le1\) 时,最小的 \(q>1\) 时,其对应的合法的 \(p\) 是唯一的。

证明

考虑反证,假设对于当前的 \(q\)\(p\)\(p+1\) 都是合法的,那么有 \(\frac AB<\frac pq<\frac {p+1}q<\frac CD\le1\)。又因为 \(\frac{p+1}q\le1\),所以 \(p+1\le q\),进而有:

\[pq\le pq+q-(p+1)=(p+1)(q-1) \]

所以 \(\frac p{q-1}\le\frac{p+1}q\),又因为显然 \(\frac p{q-1}>\frac pq\),所以 \(q-1\) 也是一个合法的解,与反证假设矛盾。

于是我们直接进行递归求解即可,其总复杂度为 \(O(T\log\max\{A,B,C,D\})\)

参考资料:AT官方题解

Code:

#include<iostream>
#include<cmath>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,l,r) for(int i=(l);i>=(r);i--)
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pr;
inline pr dfs(ll a,ll b,ll c,ll d){
	if(a>=b){
		ll t=a/b;
		pr p=dfs(a-t*b,b,c-t*d,d);
		return make_pair(p.first+p.second*t,p.second);
	}
	if(c>d)return make_pair(1ll,1ll);
	pr p=dfs(d,c,b,a);
	return make_pair(p.second,p.first);
}
int main()
{
	int it;
	cin>>it;
	while(it--){
		ll ia,ib,ic,id;
		scanf("%lld %lld %lld %lld",&ia,&ib,&ic,&id);
		printf("%lld\n",dfs(ia,ib,ic,id).second);
	}
	return 0;
}
posted @ 2025-06-02 23:05  FugiPig  阅读(8)  评论(0)    收藏  举报