D武器大师的宝贝(最大相交区间,异或,最大公约数)

Description

武器大师有两堆宝贝箱子,每个箱子都有着自己的一个编号。

为了输入方便,每堆箱子编号都是连续的。

现在他想分别从两堆箱子中各等概率的选择一个箱子,但是只有他选择的两个箱子编号异或(位运算)之后为0,他才能获得奖励。

现在他想请你算算每次他能获得奖励的概率。

为了防止精度误差,你需要输出一个形如a/b的最简分数。

特别的,如果概率为0,你需要输出0/1。

(有人不知道啥是异或吗?

Input

第一行一个正整数T(1<=T<=1000),表示数据组数。

接下来每一行都有一组数据,每组数据输入4个整数a,b,c,d,表示两堆箱子的编号区间分别为[a,b],[c,d]。

(a, b, c, d∈[0, 1e9],a ≤ b,c ≤ d)

Output

对每组数据输出他能获得奖励的概率。一个形如a/b的最简分数。

特别的,如果概率为0,你需要输出0/1。

Sample Input 1

2
1 2 2 3
1 2 2 4
Sample Output 1

1/4
1/6
Hint

样例一:有两堆箱子,第一堆箱子有2个箱子,编号为分别为1,2。第二堆箱子也有2个箱子,编号为2,3。只有当选择的箱子对是(2,2)时他才能获得奖励。

解释位运算异或:00=0,01=1,10=1,11=0.

例如:3^5 = 011^101=110

Source
2019年集训队选拔赛

思路:比赛的时候直接暴力for去弄的,没弄清楚异或的意义,题目中异或为0的意思就是相等。那么此题就可以转换为求最大相交区间。注意,暴力枚举相交区间也是很容易出错的,类似2018年CSP的第二题(好像是卖菜题),可以用快速求区间相交的算法int s = min(b,d) - max(a,c) + 1;这个是我在写2018年选拔赛题目时看CWJ学长博客看到的。https://blog.csdn.net/I_believe_CWJ/article/details/80297476

看懂题目以后其实是一道水题,暴力if也可以出的来。事实上比赛的时候过2题的并不多(至少一道线段树模板题+这道题),我也在比赛的时候没想出这道题,而且异或放在if里面会有诡异错误。。。这说明学习的基础很不扎实啊,要加油啊。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

#define ll long long
ll gcd(ll n,ll m)
{
	return m==0?n:gcd(m,n%m);
}

int main()
{
	ll T;
	scanf("%lld",&T);
	while(T--)
	{
		ll a,b,c,d;
		scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
		int len;
		int s = min(b,d) - max(a,c) + 1;
		len = max(0,s);
		ll m = (b - a + 1) * (d - c + 1);
		if(s == 0)
			printf("0/1
");
		else 
			printf("%lld/%lld
",len/gcd(m,len),m/gcd(m,len));
		
		
	}
}

原文地址:https://www.cnblogs.com/tomjobs/p/10617592.html