bzoj2187

多组询问,每次给出 $a, b, c, d$,求满足 $\frac{a}{b}  < \frac{p}{q} < \frac{c}{d}$ 的所有二元组 $(p, q)$ 中 $p$ 为第一关键字,$q$ 为第二关键字排出来的字典序最小的那一对。

分析:

设计函数 $f(a,b,p,q,c,d)$.

按照题目中保证 $q$ 最小的要求考虑该函数的几个边界:

1. $\left \lfloor \frac{a}{b} \right \rfloor-1 \leq \left \lceil \frac{c}{d} \right \rceil-1$,这个时候 $p = \left \lfloor \frac{a}{b} \right \rfloor+1, q=1$ 时字典序最小

2. $a=0$ 时,这个时候 $0 < \frac{p}{q} < \frac{c}{d} \Rightarrow q > \frac{dp}{c}$,显然 $p=1, q=\left \lfloor \frac{c}{d} \right \rfloor+1$ 时字典序最小

然后考虑辗转相除缩小问题规模:

1. $a > b\ or \ c > d$:原式等价于:$\frac{a\%b}{b} < \frac{p}{q}-\left \lfloor \frac{a}{b} \right \rfloor < \frac{c}{d}-\left \lfloor \frac{a}{b} \right \rfloor$

即:$f(a, b, p, q, c,d) = f(a \% b, b, p, q, c-{\left \lfloor \frac{a}{b} \right \rfloor}d), p+= {\left \lfloor \frac{a}{b} \right \rfloor}q$.

2. $a \leq b \ and \ c \leq d$:原式等价于:$\frac{d}{c} < \frac{q}{p} < \frac{b}{a}$.

即:$f(a,b,p,q,c,d) = f(d,c,q,p,b,a)$,这样就回到了第一步。

#include<bits/stdc++.h>
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 f(ll a, ll b, ll& p, ll& q, ll c, ll d)
{
//calc(a, b); calc(c, d); //可以不用
if(!a){p=; q=d/c+; return;}
ll x = a/b+, y = c/d+(c%d>)-;
if(x <= y){q=, p=x; return;}
if(a <= b && c <= d) f(d, c, q, p, b, a);
else{ f(a%b, b, p, q, c-a/b*d, d); p += a/b*q;}
} int main()
{
while(scanf("%lld%lld%lld%lld", &a, &b, &c, &d) == )
{
f(a, b, p, q, c, d);
printf("%lld/%lld\n", p, q);
}
return ;
}

hdu3637

给出两个非负有理数 $A, B$($A < B$),你的任务是发现一个分数介于A和B,在这个区间内可能有许多分数,请输出分子加分母和最小的分数。

分析:

首先,解决输入问题,无线循环小数很容易转换成分数。

因为0.[1]=1/9, 0.0[1]=1/99, 0.00[1]=1/999...

将小数分成括号部分和非括号部分即可。

问题转换成求 $\frac{a}{b} < \frac{p}{q} < \frac{c}{d}$,且 $p+q$ 最小。

可以推导出 $p$ 最小时,$p+q$ 就最小,于是套类欧几里得模板即可。

//交上去会MLE,不知道咋解决

#include<bits/stdc++.h>
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 f(ll a, ll b, ll& p, ll& q, ll c, ll d)
{
//calc(a, b); calc(c, d); //可以不用
if(!a){p=; q=d/c+; return;}
ll x = a/b+, y = c/d+(c%d>)-;
if(x <= y){q=, p=x; return;}
if(a <= b && c <= d) f(d, c, q, p, b, a);
else{ f(a%b, b, p, q, c-a/b*d, d); p += a/b*q;}
} char s[];
void input(ll& a, ll& b)
{
scanf("%s", s);
int len = strlen(s);
ll tmp1 = , tmp2 = , flag = , is_point=, is_kh=, cnt1=, cnt2=;
for(int i = ;i < len;i++)
{
if(s[i] == ']') continue;
if(s[i] == '.'){is_point=;continue;}
if(s[i] == '['){is_kh=;continue;}
if(is_point&&!is_kh) cnt1 = cnt1*;
if(is_point) cnt2 = cnt2*+;
if((!is_kh)) tmp1 = tmp1* + (s[i]-'');
else tmp2 = tmp2* + (s[i]-'');
}
calc(tmp1, cnt1);
if(cnt2 == )
{
calc(tmp2, cnt2);
a = tmp1, b=cnt1;
}
else a = tmp1*cnt2+tmp2*cnt1, b=cnt1*cnt2;
if(!a) calc(a, b);
} int main()
{
int T, kase=;
scanf("%d", &T);
while(T--)
{
input(a, b);input(c, d);
//printf("%lld %lld %lld %lld\n", a, b, c, d);
f(a, b, p, q, c, d);
printf("Case %d: %lld/%lld\n", ++kase, p, q);
}
return ;
}

参考链接:

1. https://blog.csdn.net/dreaming__ldx/article/details/86769792

2. https://blog.csdn.net/hqd_acm/article/details/6648027

bzoj2187 fraction&&hdu3637 Find a Fraction——类欧几里得的更多相关文章

  1. [ZZOJ#31]类欧几里得

    [ZZOJ#31]类欧几里得 试题描述 这是一道模板题. 给出 \(a, b, c, n\),请你求出 \(\sum_{x=0}^n{\lfloor \frac{a \cdot x + b}{c} \ ...

  2. 算法马拉松35 E 数论只会Gcd - 类欧几里得 - Stern-Brocot Tree - 莫比乌斯反演

    题目传送门 传送门 这个官方题解除了讲了个结论,感觉啥都没说,不知道是因为我太菜了,还是因为它真的啥都没说. 如果 $x \geqslant y$,显然 gcd(x, y) 只会被调用一次. 否则考虑 ...

  3. 类欧几里得模板 p5170

    //类欧几里得的模板题 p5170 //求这三个式子: //第一个跟后两个没关联 //后两个跟其余两个都有关联: #include<cstdio> #include<algorith ...

  4. 2019HDU多校第五场A fraction —— 辗转相除法|类欧几里得

    题目 设 $ab^{-1} = x(mod \ p)$,给出 $x,p$,要求最小的 $b$,其中 $0< a < b, \ 1 < x<p,\ 3 \leq x\leq {1 ...

  5. 2019.02.06 bzoj2987: Earthquake(类欧几里得)

    传送门 题意简述:求满足ax+by+c≤0ax+by+c\le0ax+by+c≤0的二元组(x,y)(x,y)(x,y)对数. 思路: 类欧几里得算法模板题. 把式子变化一下变成:求满足0≤y≤−ax ...

  6. JZOJ3492数数&&GDOI2018超级异或绵羊——位&&类欧几里得

    JZOJ3492 数数(count) 我们知道,一个等差数列可以用三个数A,B,N表示成如下形式:  B+A,B+2A,B+3A⋯B+NA ztxz16想知道对于一个给定的等差数列,把其中每一项用二进 ...

  7. 2019牛客多校九 I. KM and M (类欧几里得)

    大意: 给定$N,M$, 求$\sum\limits_{K=1}^N \text{(KM)&M}$ 考虑第$i$位的贡献, 显然为$\lfloor\frac{KM}{2^i}\rfloor$为 ...

  8. Kattis - itsamodmodmodmodworld It's a Mod, Mod, Mod, Mod World (类欧几里得)

    题意:计算$\sum\limits_{i=1}^n[(p{\cdot }i)\bmod{q}]$ 类欧模板题,首先作转化$\sum\limits_{i=1}^n[(p{\cdot}i)\bmod{q} ...

  9. 2019.02.06 bzoj2187: fraction(类欧几里得)

    传送门 题意简述:多组询问,每次给出a,b,c,da,b,c,da,b,c,d,求满足ab<pq<cd\frac ab<\frac pq<\frac cdba​<qp​& ...

随机推荐

  1. x58平台 服务器电源配置 tdp

    我的机器配置: 处理器:    Intel(R) Xeon(R) CPU           X5660  @ 2.80GHz *2主板:    TYAN Tyan Tank GT20-B7002LN ...

  2. 使用mysqldump命令进行mysql数据库备份

    1.用法 mysqldump -uroot -p --databases test > /home/test.sql mysqldump -uroot -h127.0.0.1 -p --data ...

  3. SpringBoot第七篇:整合Mybatis-Plus

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10881666.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言   一看这个名 ...

  4. Redis学习之intset整数集合源码分析

    1.整数集合:整数的集合,升序排序,无重复元素 2.整数集合intset是集合键的底层实现之一,当一个集合只包含整数值的元素,并且这个集合的元素数量不多时,redis会使用整数集合作为集合键的底层实现 ...

  5. ForkJoin和流式操作

    Fork/Join框架:在必要的情况下,将一个大任务,进行拆分(fork) 成若干个子任务(拆到不能再拆,这里就是指我们制定的拆分的临界值),再将一个个小任务的结果进行join汇总. 采用juc包的f ...

  6. Sitecore 创建并实施自定义营销分类

    在Sitecore体验平台中,分类法是一种组织项目的方式.您可以应用分类标签来识别广告系列,引荐渠道以及有关营销活动的其他信息.这使您可以识别和跟踪各种营销活动之间的关系,从而更深入地了解广告系列的效 ...

  7. scala的应用--UDF:用户自定义函数

    在window10下安装了hadoop,用ida创建maven项目. <properties> <spark.version>2.2.0</spark.version&g ...

  8. 用 ubuntu 自带的 gome-screenshot 来实现类似QQ截图那样的功能,同时设置键盘快捷键

    在window下习惯了使用ctrl+Alt+A截图,在linux还真有点不习惯,所以下面介绍一下替代的用法. 打开 ubuntu 的系统设置-->键盘-->快捷键:界面如下: 01 添加一 ...

  9. WPF DataGrid 使用CellTemplateSelector 时SelectTemplate方法Item参数为NULL

    首先说明 在SelectTemplate中并Item参数并不是真的一直为Null.而是先执行空参数,之后再会执行有参数的. 至于原因 我也不知道... 具体验证过程是 也就说 做好非空检测即可

  10. 五、Hexo静态博客背景及界面显示优化配置

    示例预览:我的主页 背景图片添加 自动切换背景 静态本地背景 首先将已选定的背景图片放到博客根目录下的\source\images下 ​ 示例:D:\Blog\source\images\backgr ...