题目
题意概要
求这个不可重集合的大小:
{
x
∩
y
∣
x
∈
[
l
x
,
r
x
]
,
y
∈
[
l
y
,
r
y
]
,
x
∪
y
=
T
}
\{x\cap y|x\in[l_x,r_x],y\in[l_y,r_y],x\cup y=T\}
{x∩y∣x∈[lx,rx],y∈[ly,ry],x∪y=T}
其中 ∩ \cap ∩ 表示按位与, ∪ \cup ∪ 表示按位或。
数据范围与提示
所有数据均为
[
0
,
2
60
)
[0,2^{60})
[0,260) 内的整数,同时保证
l
x
≤
r
x
l_x\le r_x
lx≤rx 且
l
y
≤
r
y
l_y\le r_y
ly≤ry 。
思路
可以看大佬的博客,并在评论区留下 “湘妹儿~” 的评论 😃
一眼数位 d p dp dp 题……当然是用二进制考虑。大致思路仅需一眼,具体做法头发掉光 😢
我们来看看这道题到底怎么做。用 d p dp dp 来做——非常慢的 d p dp dp 。用 f ( i , p , q ) f(i,p,q) f(i,p,q) 表示,仅仅考虑前 i − 1 i-1 i−1 位时, x x x 的取值为 p p p , y y y 的取值为 q q q ,能够拿到多少个不同的按位与的值。不妨用 p = p r e i ( x ) p=pre_i(x) p=prei(x) 来表示 x x x 的前 i − 1 i-1 i−1 位为 p p p ,那么用数学语言描述就是 f ( i , p , q ) = c a r d { x ∩ y ∣ x ∈ [ l x , r x ] , y ∈ [ r x , r y ] , x ∪ y = T , p = p r e i ( x ) , q = p r e i ( y ) } f(i,p,q)=card\{x\cap y|x\in[l_x,r_x],y\in[r_x,r_y],x\cup y=T,p=pre_i(x),q=pre_i(y)\} f(i,p,q)=card{x∩y∣x∈[lx,rx],y∈[rx,ry],x∪y=T,p=prei(x),q=prei(y)}
毕竟数位 d p dp dp 嘛 😎
然后我们枚举当前位的取值就很好做了……吗?用 ( a 0 , b 0 ) (a_0,b_0) (a0,b0) 表示 x x x 的第 i i i 位为 a 0 a_0 a0 而 y y y 的第 i i i 位为 b 0 b_0 b0 的情况,那么 ( 1 , 0 ) (1,0) (1,0) 和 ( 0 , 1 ) (0,1) (0,1) 是有交集的,因为按位与的值没有出现区别,但是 x , y x,y x,y 的值不一样了。
这两种情况怎么处理?我们给出一个惊世骇俗的结论:二者的方案有包含关系!
首先,我们说明一下,既然在这一位上既可以取 ( 0 , 1 ) (0,1) (0,1) 也可以取 ( 1 , 0 ) (1,0) (1,0) ,那么取 1 1 1 的就一定摆脱下界;取 0 0 0 就一定摆脱上界。这个道理很简单,可以取 0 0 0 ,那么取 1 1 1 就没有顶住下界。严谨证明不给出了,太简单。
如果结论是错误的,那么就有两个不同的按位与的值,分属于两者。也就是:我们试图证明 A − A ∩ B ≠ ϕ A-A\cap B\ne\phi A−A∩B=ϕ 且 B − A ∩ B ≠ ϕ B-A\cap B\ne\phi B−A∩B=ϕ ,于是, ∃ x ∈ A , y ∈ B \exist x\in A,y\in B ∃x∈A,y∈B 满足 x ∉ B , y ∉ A x\not\in B,y\not\in A x∈B,y∈A 。
我们可以假设这个方案真实存在,后面的数字假设出来。对于后面某一个按位或为 1 1 1 的位置(因为按位或为 0 0 0 的位置没得选 😅),存在三种情况: ( 0 , 1 ) , ( 1 , 0 ) , ( 1 , 1 ) (0,1),(1,0),(1,1) (0,1),(1,0),(1,1) 。我们都来看一看:
-
(
1
,
0
)
(1,0)
(1,0) 组合看图片上面所说的,
0
0
0 可以更改为
1
1
1 。这个数字在增大,而前面的
0
0
0 让它摆脱了上界,所以不会超出范围。
同时,第 i i i 位的选择仍然是被固定住的。原本前面就没法选 1 1 1 ,现在你又增大了一点,就更不能选 1 1 1 了! -
(
1
,
1
)
(1,1)
(1,1) 组合
类似地,将 1 1 1 更改为 0 0 0 是完全可以的。同时,第 i i i 位的选择也仍然没有增多。 -
(
0
,
1
)
(0,1)
(0,1) 组合
仔细看完,你会发现, ( 1 , 0 ) → ( 1 , 1 ) → ( 0 , 1 ) (1,0)\rightarrow (1,1)\rightarrow (0,1) (1,0)→(1,1)→(0,1) ,并且第 i i i 位的选择仍然固定。
那么,倘若真的存在两对方案 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1,y_1),(x_2,y_2) (x1,y1),(x2,y2) 并且二者仅仅属于第 i i i 位的某一个选择,那么经过这一系列调整,将会得到 ( x ′ , y ′ ) (x',y') (x′,y′) 只能属于 ( 1 , 0 ) (1,0) (1,0) 也只能属于 ( 0 , 1 ) (0,1) (0,1) ,矛盾。
我们已经成功除杂了,只需要使用 max ( f 1 , f 2 ) \max(f_1,f_2) max(f1,f2) 即可,两种情况取最大值。
但是速度有点慢,怎么办呢?原来 p , q p,q p,q 不影响后面的转移,影响转移的是,是否顶住了上下界。改成四个 b o o l bool bool 就行了。复杂度变成了 O ( 2 5 log T ) \mathcal O(2^5\log T) O(25logT) ,稳!
代码
#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;
}