一、链接
爱你一生一世
二、题目
题目描述
在2013年1月4日,这个“爱你一生一世”的特别日子,男生都想向自己的喜欢的女生表达爱意。 你准备在该死的C语言考试后,去向她(或者他?)告白。告白怎么能缺了礼物了? 经过前期的情报收集,你了解到她喜欢的一些礼物,但是可能因为消息的不准确,其中有些 礼物并不是她喜欢。为了保险,你准备从其中挑选两件不同的礼物,请问至少有一件礼物她 会喜欢的概率。
输入
第一行是一个整数K,表示样例的个数。 以后每行两个整数N(2≤N≤10,000),表示礼物的个数和M(0 ≤ M ≤ N),表示不喜欢的礼物个数。
输出
输出每个样例的结果,如果概率是0或者1,输出0,1,其他情况输出分数形式a/b,保证a和b互质。
样例输入
3 4 0 4 2 4 4
样例输出
1 5/6 0
三、题意
给定多件礼物,已知有多少件不喜欢,从所有礼物中选择两件不同的礼物,问至少有一件喜欢的概率,并且需要用分数的形式输出答案
四、代码
c++代码
#include<iostream>using namespace std;int gcd(int a,int b)
{return b>0?gcd(b,a%b):a;
}int main()
{int t;scanf("%d",&t);while(t--){int a,b;scanf("%d%d",&a,&b);//至少有一件喜欢的概率是:1-p1//p1:选中的两件都不喜欢//第二个样例:4 2//c22/c42 表示两件礼物都不喜欢,1/6int up=b*(b-1),down=a*(a-1);//同时除以2约掉了//int ans=(down-up)/down;显然不能这么算up=down-up;int k=gcd(up,down);up/=k;down/=k;if(up==0) printf("0\n");else if(up==1&&down==1) printf("1\n");else printf("%d/%d\n",up,down);}return 0;
}
c语言代码
#include<stdio.h>int gcd(int a,int b)
{return b>0?gcd(b,a%b):a;
}int main()
{int t;scanf("%d",&t);while(t--){int x,y;scanf("%d%d",&x,&y);int up=y*(y-1),down=x*(x-1);up=down-up;int k=gcd(up,down);up/=k;down/=k;if(up==0) printf("0\n");else if(up==1&&down==1) printf("1\n");else printf("%d/%d\n",up,down);}return 0;
}
五、总结
1.关于最大公约数函数gcd,可以参考这一篇博客:最小公倍数题解:湘大oj1075 辗转相除法
使用辗转相除法的题目推荐:oj1075,oj1392
2.逆向思维:至少有一件喜欢的反面是一件都不喜欢,用1减去一件都不喜欢的概率就是我们要求的结果
3.一件都不喜欢:假设所有礼物的件数是x,不喜欢的礼物件数是y,从不喜欢的礼物中挑选两件,,从所有礼物中挑选两件,,把这两个数相除就是一件都不喜欢的概率,但是注意,这两个数字是整型数字,不可以直接相除,直接相除会向下取整,损失精度
4.上面两个数字,,,都有一个除以2的步骤,分子分母同时乘以2,可以抵消,分子变成y*(y-1),分母变成x*(x-1),用1减去这个分式,等于{x*(x-1)-y*(y-1)}/{x*(x-1)}
5.到目前为止只有没有计算分式的数值,就没有损失精度(我们只是知道是这样表示,但是没有用计算机把这个式子表示出来),用一个变量up表示分子,存储x*(x-1)-y*(y-1),用一个变量down表示分母,存储x*(x-1),求分子分母的最大公约数,分子分母同时除以最大公约数
int k=gcd(up,down);
up/=k;
down/=k;
6.然后进行条件判断就可以以分式形式输出答案了(事实上一直没有计算准确值)
7.需要以分式输出就联想最大公约数!
六、精美图片