#题解 P2118 [NOIP2014 普及组] 比例简化

好久没更新了,今天写篇题解,题目是P2118 [NOIP2014 普及组] 比例简化

看题

题目描述

在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果。例如,对某一观点表示支持的有14981498 人,反对的有 902902人,那么赞同与反对的比例可以简单的记为1498:9021498:902

不过,如果把调查结果就以这种方式呈现出来,大多数人肯定不会满意。因为这个比例的数值太大,难以一眼看出它们的关系。对于上面这个例子,如果把比例记为5:35:3,虽然与真实结果有一定的误差,但依然能够较为准确地反映调查结果,同时也显得比较直观。

现给出支持人数A,反对人数BB,以及一个上限LL,请你将AABB化简为AA’比BB’,要求在AA’和BB’均不大于LLAA’和BB’互质(两个整数的最大公约数是11)的前提下,AA/B/BA/B ≥ A/BAA/B/BA/B - A/B的值尽可能小。

(本题目为2014NOIP普及T2)

输入格式

共一行,包含三个整数A,B,LA,B,L,每两个整数之间用一个空格隔开,分别表示支持人数、反对人数以及上限。

输出格式

共一行,包含两个整数AA’,BB’,中间用一个空格隔开,表示化简后的比例。

输入输出样例

输入 #1
1498 902 10
输出 #1
5 3

说明/提示

对于100%100\%的数据,1A1,000,000,1B1,000,000,1L100,A/BL1 ≤ A ≤ 1,000,000,1 ≤ B ≤ 1,000,000,1 ≤ L ≤ 100,A/B ≤ L




实现

众所周知,分子相同,分母扩大,分数减小;分母相同,分子扩大,分数扩大。
利用这个性质,我们就可以从11\frac{1}{1}开始枚举,如果小于原分数ab\frac{a}{b},那么分子加一;如果大于原分数ab\frac{a}{b},那么分母加一。用式子就可以表达为:

  1. if(ij\frac{i}{j} >= ab\frac{a}{b}) ⟹ j++j++;
  2. if(ij\frac{i}{j} <= ab\frac{a}{b}) ⟹ i++i++;

PS:ij=i,j1\small\color{grey}PS:i表示分子;j表示分母\\\color{red}注意:“=”不要忘记!i,j赋值为1!
那分数如何比较呢?float?double?不,他们都有限制,不一定是最准确的答案,但是——根据小学数学:我们知道分数的性质,可以“交叉相乘”作比较。如下图:

修改代码…… 这个就不展示了吧……

接下来我们可以扩充上文中的第一个if语句。加上如下功能:

如果这个数大于原分数ab\frac{a}{b},又小于上一次记录的分数,也就意味着与原分数ab\frac{a}{b}的差更小,就可以将这个分数记录下来。

if(i*b >= j*a){
            if(ansj*i < ansi*j){
                ansj = j;
                ansi = i;
            }
            j++;
        }else{
            i++;
        }

PS:ansiiansjjansiansjlansi=lansj=1\small \qquad\color{grey}{PS:ansi用于记录分子i;ansj用于记录分子j}\\\qquad\color{red}注意:ansi和ansj要赋值为一个较大的数,所以采用l范围内最大的分数赋值,\\即ansi=l,ansj=1

接着在一个死循环中不断执行这一段程序,就可以得到正确答案,但是,ii & jj 均不能超过 ll

就可以在代码中加入两个if语句,顺手加上输出,这道题就解决了。

完整代码

不要抄

#include<bits/stdc++.h>
using namespace std;
int a,b,l;
int i=1,j=1;//i/j
int ansi,ansj=1;
int main(){
    cin >> a >> b >> l;
    ansi=l;
    while (1)
    {
        if(i*b >= j*a){
            if(ansj*i < ansi*j){
                ansj = j;
                ansi = i;
            }
            j++;
            if(j > l){
                break;
            }
        }else{
            i++;
            if(i > l){
                break;
            }
        }

    }
    cout << ansi << " " << ansj;
    return 0;
}