F-异或-牛客小白月赛3

链接:https://www.nowcoder.com/acm/contest/87/F
来源:牛客网

题目描述
Cwbc想测试一下他的加密协议,以便防止其他人偷看他给XHRlyb的信。
Cwbc提出了这样一个问题:在区间[a,b]和区间[c,d]中分别等概率随机选择一个整数,两者异或之后等于0的概率是多少?
XHRlyb 一眼就看出了这个题目的答案,但她想让你计算一下这个概率。为了防止精度误差,你只需要输出一个形如a/b的最简分数。特别的,如果概率为0,你需要输出0/1。
聪明的你在仔细阅读题目后,一定可以顺利的解决这个问题!
输入描述:
输入数据有多行,每行有四个非负整数a, b, c, d。
输出描述:
输出数据应有多行,每行有一个表示答案,形如x/y的最简分数。
示例1
输入

1 2 3 4
输出

0/1
示例2
输入

1 2 2 3
输出

1/4
备注:
a, b, c, d∈[0, 109]。
a ≤ b,c ≤ d
1 ≤ T ≤ 1000。

[分析]
异或最终为0只有一个可能,就是两个数字相同
所以题意就是两个区间里有多少相同的数字
所以我们要输出的就是:相同数字个数/(第一个区间长度*第二个区间长度)

但是麻烦就麻烦在确定相同数字个数

我的方法是将区间写成结构体
只记区间头和尾
关键的地方来来,特别方便的
对两个区间排序(注意哦不是某一个区间里面的排序)
把区间头小的放前面,如果区间头一样大,那么把区间尾小的放前面(这样可以少判断非常多情况,写起来方便)
所以现在要做的就是把第二个区间的区间头-min(第一个区间头,第二个区间头)+1,这个就是相同数字的个数

为什么是第二个区间的区间头-min(第一个区间头,第二个区间头)+1呢?
因为前面已经排序了,所以第二个区间头肯定大于等于第一个区间头,他更大。不懂就画个图吧。

得到了相同数字的个数,基本上也就做完了
然后需要关注的就是最简分式
写一个gcd(最大公约数)就完事了,分子分母都除以gcd我们就可以输出答案了。

[代码]

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct Node
{
    ll a, b;
}no[2];

bool cmp(Node x, Node y)
{
    if (x.a != y.a)return x.a < y.a;
    else return x.b < y.b;
}

ll gcd(ll a, ll b)
{
    return b ? gcd(b, a%b) : a;
}

int main()
{
    while (scanf("%lld%lld%lld%lld",&no[0].a, &no[0].b, &no[1].a, &no[1].b)!=EOF)
    {
        if (no[0].a>no[0].b)swap(no[0].a, no[0].b);
        if (no[1].a>no[1].b)swap(no[1].a, no[1].b);
        sort(no, no + 2, cmp);
        ll bet = max((ll)0, min(no[0].b, no[1].b) - no[1].a + 1);//相同数字的个数
        if (bet == 0)
        {
            printf("0/1\n");
            continue;
        }

        ll n = no[0].b - no[0].a + 1;
        ll m = no[1].b - no[1].a + 1;
        ll gcdd = gcd(n*m, bet);
        printf("%lld/%lld\n", bet / gcdd, n*m / gcdd);
    }
}

猜你喜欢

转载自blog.csdn.net/q435201823/article/details/80295549