题目
题意概要
求这个不可重集合的大小:
其中 表示按位与, 表示按位或。
数据范围与提示
所有数据均为 内的整数,同时保证 且 。
思路
可以看大佬的博客,并在评论区留下 “湘妹儿~” 的评论 😃
一眼数位 题……当然是用二进制考虑。大致思路仅需一眼,具体做法头发掉光 😢
我们来看看这道题到底怎么做。用 来做——非常慢的 。用 表示,仅仅考虑前 位时, 的取值为 , 的取值为 ,能够拿到多少个不同的按位与的值。不妨用 来表示 的前 位为 ,那么用数学语言描述就是
毕竟数位 嘛 😎
然后我们枚举当前位的取值就很好做了……吗?用 表示 的第 位为 而 的第 位为 的情况,那么 和 是有交集的,因为按位与的值没有出现区别,但是 的值不一样了。
这两种情况怎么处理?我们给出一个惊世骇俗的结论:二者的方案有包含关系!
首先,我们说明一下,既然在这一位上既可以取 也可以取 ,那么取 的就一定摆脱下界;取 就一定摆脱上界。这个道理很简单,可以取 ,那么取 就没有顶住下界。严谨证明不给出了,太简单。
如果结论是错误的,那么就有两个不同的按位与的值,分属于两者。也就是:我们试图证明 且 ,于是, 满足 。
我们可以假设这个方案真实存在,后面的数字假设出来。对于后面某一个按位或为 的位置(因为按位或为 的位置没得选 😅),存在三种情况: 。我们都来看一看:
- 组合看图片上面所说的, 可以更改为 。这个数字在增大,而前面的 让它摆脱了上界,所以不会超出范围。
同时,第 位的选择仍然是被固定住的。原本前面就没法选 ,现在你又增大了一点,就更不能选 了! - 组合
类似地,将 更改为 是完全可以的。同时,第 位的选择也仍然没有增多。 - 组合
仔细看完,你会发现, ,并且第 位的选择仍然固定。
那么,倘若真的存在两对方案 并且二者仅仅属于第 位的某一个选择,那么经过这一系列调整,将会得到 只能属于 也只能属于 ,矛盾。
我们已经成功除杂了,只需要使用 即可,两种情况取最大值。
但是速度有点慢,怎么办呢?原来 不影响后面的转移,影响转移的是,是否顶住了上下界。改成四个 就行了。复杂度变成了 ,稳!
代码
#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
typedef long long int_;
inline int_ readint(){
int_ a = 0; char c = getchar(), f = 1;
for(; c<'0' or c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c and c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
int_ T, lx, ly, rx, ry, dp[60][2][2][2][2];
# define a_ a|((lx>>x&1) < i)
# define b_ b|(i < (rx>>x&1))
# define c_ c|((ly>>x&1) < j)
# define d_ d|(j < (ry>>x&1))
# define sxy a_,b_,c_,d_
int_ work(int x,int a,int b,int c,int d){
if(x == -1) // 每一位都被考虑了
return 1; // 仅有自己一种
int_ &zxy = dp[x][a][b][c][d];
if(zxy != -1) return zxy; zxy = 0;
int_ chose = 0; // 二者取max
for(int i=0; i<2; ++i)
for(int j=0; j<2; ++j)
if((i|j) == (T>>x&1)) // 满足按位或条件
if(a or (lx>>x&1) <= i) // x下界
if(b or i <= (rx>>x&1)) // x上界
if(c or (ly>>x&1) <= j) // y下界
if(d or j <= (ry>>x&1)) // y上界
if((a&b) == 1) zxy = work(x-1,sxy);
else chose = max(chose,work(x-1,sxy));
return zxy += chose;
}
int main(){
memset(dp,-1,sizeof dp);
T = readint();
lx = readint(), rx = readint();
ly = readint(), ry = readint();
printf("%lld\n",work(59,0,0,0,0));
return 0;
}