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));
}
}