bzoj2187: fraction(类欧几里得)

本文介绍了一道数学题目,涉及到多组询问,每次给出四个数a, b, c, d,目标是找到满足ba < qp < dc条件的最小字典序二元组(p, q),其中q为主关键字,p为次关键字。通过设计函数f(a, b, p, q, c, d),探讨了不同边界情况和如何递归缩小问题规模,最终给出了问题的解决方案和代码实现。" 108004083,9095228,Oracle 11g安装教程与数据库操作指南,"['数据库', 'Oracle', 'Python开发', '数据库操作', 'PLSQL']
摘要由CSDN通过智能技术生成

传送门
题意简述:多组询问,每次给出 a , b , c , d a,b,c,d a,b,c,d,求满足 a b &lt; p q &lt; c d \frac ab&lt;\frac pq&lt;\frac cd ba<qp<dc的所有二元组 ( p , q ) (p,q) (p,q) q q q为第一关键字, p p p为第二关键字排出来字典序最小的那一对。


思路:
设计函数 f ( a , b , p , q , c , d ) f(a,b,p,q,c,d) f(a,b,p,q,c,d)
按照题目中保证 q q q最小的要求考虑该函数几个边界:

  1. ⌊ a b ⌋ + 1 ≤ ⌈ c d ⌉ − 1 \left\lfloor\frac ab\right\rfloor+1\le\left\lceil\frac cd\right\rceil-1 ba+1dc1,这个时候 p = ⌊ a b ⌋ + 1 , q = 1 p=\left\lfloor\frac ab\right\rfloor+1,q=1 p=ba+1,q=1时字典序最小。
  2. a = 0 a=0 a=0,这个时候 0 &lt; p q &lt; c d ⇒ q &gt; d p c 0&lt;\frac pq&lt;\frac cd\Rightarrow q&gt;\frac{dp}c 0<qp<dcq>cdp,显然 p = 1 , q = ⌊ c d ⌋ + 1 p=1,q=\left\lfloor\frac cd\right\rfloor+1 p=1,q=dc+1的时候字典序最小。

然后考虑如何辗转缩小问题规模:

  1. a &gt; b a&gt;b a>b o r or or c &gt; d : 原 式 ⇔ a % b b &lt; p q − ⌊ a b ⌋ &lt; c d − ⌊ a b ⌋ c&gt;d:原式\Leftrightarrow\frac{a\%b}b&lt;\frac pq-\left\lfloor\frac ab\right\rfloor&lt;\frac cd-\left\lfloor\frac ab\right\rfloor c>d:ba%b<qpba<dcba
    ⇒ f ( a , b , p , q , c , d ) = f ( a % b , b , p , q , c − ⌊ a b ⌋ d , d ) , p + = ⌊ a b ⌋ q \Rightarrow f(a,b,p,q,c,d)=f(a\%b,b,p,q,c-\left\lfloor\frac ab\right\rfloor d,d),p+=\left\lfloor\frac ab\right\rfloor q f(a,b,p,q,c,d)=f(a%b,b,p,q,cbad,d),p+=baq
  2. a ≤ b a\le b ab a n d and and c ≤ d : 原 式 ⇔ d c &lt; q p &lt; b a c\le d:原式\Leftrightarrow \frac dc&lt;\frac qp&lt;\frac ba cd:cd<pq<ab
    ⇒ f ( a , b , p , q , c , d ) = f ( d , c , q , p , b , a ) \Rightarrow f(a,b,p,q,c,d)=f(d,c,q,p,b,a) f(a,b,p,q,c,d)=f(d,c,q,p,b,a)这样会回到第一步。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
ll a,b,c,d,p,q;
inline ll gcd(ll a,ll b){while(b){ll t=a;a=b,b=t-t/a*a;}return a;}
inline void calc(ll&a,ll&b){ll d=gcd(a,b);a/=d,b/=d;}
inline void solve(ll a,ll b,ll&p,ll&q,ll c,ll d){
	calc(a,b),calc(c,d);
	if(!a){p=1,q=d/c+1;return;}
	ll x=a/b+1,y=c/d+(c%d>0)-1;
	if(x<=y){p=x,q=1;return;}
	if(a<=b&&c<=d)return solve(d,c,q,p,b,a);
	solve(a-a/b*b,b,p,q,c-d*(a/b),d),p+=q*(a/b);
}
int main(){
	while(~scanf("%lld%lld%lld%lld",&a,&b,&c,&d))solve(a,b,p,q,c,d),printf("%lld/%lld\n",p,q);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值