好久没更新了,今天写篇题解,题目是P2118 [NOIP2014 普及组] 比例简化
看题
题目描述
在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果。例如,对某一观点表示支持的有 人,反对的有 人,那么赞同与反对的比例可以简单的记为。
不过,如果把调查结果就以这种方式呈现出来,大多数人肯定不会满意。因为这个比例的数值太大,难以一眼看出它们的关系。对于上面这个例子,如果把比例记为,虽然与真实结果有一定的误差,但依然能够较为准确地反映调查结果,同时也显得比较直观。
现给出支持人数A,反对人数,以及一个上限,请你将比化简为’比’,要求在’和’均不大于且’和’互质(两个整数的最大公约数是)的前提下,’’且’’的值尽可能小。
(本题目为2014NOIP普及T2)
输入格式
共一行,包含三个整数,每两个整数之间用一个空格隔开,分别表示支持人数、反对人数以及上限。
输出格式
共一行,包含两个整数’,’,中间用一个空格隔开,表示化简后的比例。
输入输出样例
1498 902 10
5 3
说明/提示
对于的数据,。
实现
众所周知,分子相同,分母扩大,分数减小;分母相同,分子扩大,分数扩大。
利用这个性质,我们就可以从开始枚举,如果小于原分数,那么分子加一;如果大于原分数,那么分母加一。用式子就可以表达为:
- if( >= ) ⟹ ;
- if( <= ) ⟹ ;
那分数如何比较呢?float?double?不,他们都有限制,不一定是最准确的答案,但是——根据小学数学:我们知道分数的性质,可以“交叉相乘”作比较。如下图:
修改代码…… 这个就不展示了吧……
接下来我们可以扩充上文中的第一个if语句。加上如下功能:
如果这个数大于原分数,又小于上一次记录的分数,也就意味着与原分数的差更小,就可以将这个分数记录下来。
if(i*b >= j*a){
if(ansj*i < ansi*j){
ansj = j;
ansi = i;
}
j++;
}else{
i++;
}
接着在一个死循环中不断执行这一段程序,就可以得到正确答案,但是, & 均不能超过
就可以在代码中加入两个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;
}