【题目链接】
ybt 1966:【14NOIP普及组】比例简化
洛谷 P2118 [NOIP2014 普及组] 比例简化
【题目考点】
1. 枚举
【解题思路】
解法1:枚举 保存浮点数 A B \frac{A}{B} BA
使用浮点型变量保存
A
B
\frac{A}{B}
BA的值
观察L的范围,为1~100,因此可以使用枚举算法。
- 枚举对象:i、j(i表示A’的值,j表示B’的值)
- 枚举范围:i、j的枚举范围都是1~100
- 判断条件:设
a
n
s
ans
ans保存已经出现过的满足大于等于d的最小的
i
j
\frac{i}{j}
ji值。要想找到满足
A
′
B
′
≥
A
B
\frac{A'}{B'}\ge \frac{A}{B}
B′A′≥BA的最小的
A
′
B
′
\frac{A'}{B'}
B′A′,判断条件应为:
i
j
≥
A
B
∧
i
j
<
a
n
s
\frac{i}{j} \ge \frac{A}{B}\land\frac{i}{j}<ans
ji≥BA∧ji<ans,该比较都是浮点型量之间的比较。
满足条件时使用 r i , r j ri,rj ri,rj记录当前 i i i与 j j j的值。
对于A’与B’是否互质,可以在记录结果前使用gcd函数判断二者的最大公约数是否为1。
这一步不做其实也可以。对于
i
j
=
i
′
j
′
\frac{i}{j}=\frac{i'}{j'}
ji=j′i′且
i
<
i
′
∧
j
<
j
′
i<i'\land j<j'
i<i′∧j<j′的情况,由于i与j都是从小到大遍历的,一定是先遍历到i与j互质的情况,后遍历到二者不互质的情况。在判断
i
j
<
a
n
s
\frac{i}{j}<ans
ji<ans时必须使用
<
<
<进行,即可取到先出现的情况而不取后出现的情况。最后输出
r
i
,
r
j
r_i,r_j
ri,rj
解法2:枚举 不使用浮点数
使用浮点数进行计算以及比较可能会由于其精度有限以至于无法表示真正的数学值。因此尽量使用整型量来完成计算。
算法和解法1是一样的。
枚举过程中判断条件为:
i
j
≥
A
B
∧
i
j
<
a
n
s
\frac{i}{j} \ge \frac{A}{B}\land\frac{i}{j}<ans
ji≥BA∧ji<ans
其中ans为
r
i
r
j
\frac{ri}{rj}
rjri
判断
i
j
≥
A
B
\frac{i}{j} \ge \frac{A}{B}
ji≥BA,可以使用十字相乘法,判断
i
⋅
B
≥
j
⋅
A
i\cdot B\ge j\cdot A
i⋅B≥j⋅A,这样可以避免使用浮点数。
同理,判断
i
j
<
r
i
r
j
\frac{i}{j} < \frac{ri}{rj}
ji<rjri,也可以写为
i
⋅
r
j
<
j
⋅
r
i
i\cdot rj<j\cdot ri
i⋅rj<j⋅ri
可以设
r
i
,
r
j
ri,rj
ri,rj的初值为0,表示还没有得到结果。
如果此时
i
j
≥
A
B
\frac{i}{j} \ge \frac{A}{B}
ji≥BA而且
r
i
,
r
j
ri,rj
ri,rj都为0,那么就使用
r
i
,
r
j
ri,rj
ri,rj记录当前的
i
,
j
i,j
i,j。或者当满足
i
j
≥
A
B
∧
i
j
<
r
i
r
j
\frac{i}{j} \ge \frac{A}{B}\land\frac{i}{j}<\frac{ri}{rj}
ji≥BA∧ji<rjri时记录当前的
i
,
j
i,j
i,j。
最终输出结果
r
i
,
r
j
ri,rj
ri,rj
【题解代码】
解法1:枚举 保存浮点数 A B \frac{A}{B} BA
- 写法1:判断分子分母是否互质
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
int gcd(int a, int b)
{
if(b == 0)
return a;
return gcd(b, a%b);
}
int main()
{
int a, b, l, ri, rj;//ri,rj记录结果
double d, d1, ans = INF;//mind:最小差值
cin >> a >> b >> l;
d = (double)a/b;//A/B
for(int i = 1; i <= l; ++i)//i:A' j:B'
for(int j = 1; j <= l; ++j) if(gcd(i, j) == 1)//最大公约数为1,二者互质
{
double d1 = (double)i/j;
if(d1 >= d && d1-d < ans)
{
ans = d1-d;
ri = i;
rj = j;
}
}
cout << ri << ' ' << rj;
return 0;
}
- 写法2:不判断互质
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
int main()
{
int a, b, l, ri, rj;//ri,rj记录结果
double d, d1, ans = INF;//mind:最小差值
cin >> a >> b >> l;
d = (double)a/b;//A/B
for(int i = 1; i <= l; ++i)//i:A' j:B'
for(int j = 1; j <= l; ++j)
{
double d1 = (double)i/j;
if(d1 >= d && d1-d < ans)
{
ans = d1-d;
ri = i;
rj = j;
}
}
cout << ri << ' ' << rj;
return 0;
}
解法2:枚举 不使用浮点数
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a, b, l, ri = 0, rj = 0;
cin >> a >> b >> l;
for(int i = 1; i <= l; ++i)
for(int j = 1; j <= l; ++j)
if(i*b >= a*j && (ri == 0 && rj == 0 || i*rj < j*ri))
ri = i, rj = j;
cout << ri << ' ' << rj;
return 0;
}

本文介绍了如何解决比例简化的问题,主要涉及枚举方法和最大公约数的应用。通过枚举A'和B'的值,找到使A'/B'最接近A/B的比例,并确保A'与B'互质。两种解题思路分别包括使用最大公约数函数判断互质和不进行判断。代码示例展示了这两种方法的实现,帮助理解算法细节。
534

被折叠的 条评论
为什么被折叠?



