本题的思路主要有三点:

1.何时会出现二者异或后等于0

2.如何确定边界(题目虽然保证了a\leb和c\led ,但无法确定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,主播祝你稳拿金牌吧()