当前位置: 代码迷 >> 综合 >> HDU 5661 Claris and XOR(异或,贪心)
  详细解决方案

HDU 5661 Claris and XOR(异或,贪心)

热度:20   发布时间:2023-12-08 10:20:16.0

题目链接:
HDU 5661 Claris and XOR
题意:
给定区间 [a,b] [c,d] ,求 x[a,b] y[c,d] 使得 xy 的值最大?输出最大的值。
数据范围: ab1018,cd1018
分析:
从后往前贪心。假设当前考虑到第 i 位,令 delt=1<<i 。我们最好是能让只是 x 加上 delt 或者只是 y 加上 delt 。对于每种情况需要考虑加上 delt 之后是否还能属于相应的区间,但是因为还有较低的位上没有考虑,直接考虑合法性的话比较难,可以考虑不合法的情况,也就是最大值比区间左端点小,最小值比区间右端点大。
例如对于 x+delt 如果考虑之后的低位的话,最小值是: Min=x+delt (低位全为0),最大值为: Max=x+delt+delt?1 (低位全为1),如果 Min>bMax<a 那么就是不合法的,也就是说 x 不能加上 delt ,否则 x 可以加上 delt
但是我们还要同时考虑 x+delty+delt 能否同时实现,尽管不论能否同时实现两者的异或在这一位上都为0,但是如果不考虑的话,就相当于把 xy 的值缩小了,接下来低位时判断 x+delt 是否属于 [a,b] y+delt 是否属于 [c,d] 会有影响。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long ll;int T;
ll a, b, c, d;bool check(ll x, ll y, int pos)
{ll extra = ((ll)1 << pos) - 1;ll xx = x + extra, yy = y + extra;if (x > b || xx < a) return false;if (y > d || yy < c) return false;return true;
}int main()
{scanf("%d", &T);while (T--) {scanf("%lld%lld%lld%lld", &a, &b, &c, &d); ll x = 0, y = 0;for (int i = 62; i >= 0; --i) {ll delt = (ll)1 << i;if (check(x + delt, y, i)) x += delt;else if (check(x, y + delt, i)) y += delt;else if (check(x + delt, y + delt, i)) x += delt, y += delt;}printf("%lld\n", x ^ y);}return 0;
}