本题的思路主要有三点:
1.何时会出现二者异或后等于0
2.如何确定边界(题目虽然保证了ab和c
d ,但无法确定a、c的大小关系和b、d的大小关系)
3.如何输出答案
第一个点,如果两数的二进制在某一位上是不一样的,那么就说明异或后一定会得到一个大于0的数,反之,只有当位数相同并且所有位上的数字全都一样时,才可以异或为0——即二者完全相同
因此我们要找的就是两端区间中重合的部分(也就是下图的绿色区域)
第二个点,如何确定边界呢?
我们只能知道a、c是左端点,b、d是右端点,所以看图就能够清晰的看到,要找的重合区域的左端点l是a和c的最大值,要找的重合区域的右端点r是b和d的最小值,如果r大于等于l,那么才说明存在重合部分,否则无重合部分,那么两端区间一定不会选到一样的数,所以为 0/1
第三个点,如何确定答案呢?
现在已知重合部分的区间长度,又可以算出两段区间的长度(这个应该都知道吧是r-l+1,l和r是左右端点),并且取的点都是整数
那么接下来我们用样本空间的思想去做这个题——重合区域的区间长度为min(b,d)-max(a,c),所包含的样本个数就是区间的长度
而另外两部分,因为是可以随机的从两段区间上选择,所以样本个数是两个区间的长度之积,因为总样本个数也就是这么多了
所以综上,概率就是重合区域的区间长度除两个区间的长度之积
可是又有了个新问题了,答案2/4该怎么办?分数形式应该是1/2口牙!不过我们根据观察不难发现,分子和分母约分的时候应该约去二者的最小公倍数!
所以最后答案就变成了再除以gcd的形式(详见代码吧,这里不太好展示)
void _()
{
int a, b, c, d;
while (cin >> a >> b >> c >> d)//多测并且没有给出组数的解决方案
{
int l = max(a, c), r = min(b, d);
int zi = r - l + 1;//分子的长度
if (zi < 0)//不能是负数
zi = 0;
int mu = (b - a + 1) * (d - c + 1);
if (zi == 0)//特判分子为0
{
cout << "0/1" << endl;
}
else
{//否则在zi/mu的基础再除以gcd并输出
cout << zi / gcd(zi, mu) << "/" << mu / gcd(zi, mu) << endl;
}
}
}
写了好久喵,希望能给个点赞和送点小花支持一下awa,主播在这里祝大家明天的比赛铁牌实力拿铜牌,铜牌实力拿银牌,银牌实力拿金牌,金牌实力...金牌实力tql,主播祝你稳拿金牌吧()

京公网安备 11010502036488号