題目
題意概要
求這個不可重集合的大小:
其中 表示按位與, 表示按位或。
數據範圍與提示
所有數據均爲 內的整數,同時保證 且 。
思路
可以看大佬的博客,並在評論區留下 “湘妹兒~” 的評論 😃
一眼數位 題……當然是用二進制考慮。大致思路僅需一眼,具體做法頭髮掉光 😢
我們來看看這道題到底怎麼做。用 來做——非常慢的 。用 表示,僅僅考慮前 位時, 的取值爲 , 的取值爲 ,能夠拿到多少個不同的按位與的值。不妨用 來表示 的前 位爲 ,那麼用數學語言描述就是
畢竟數位 嘛 😎
然後我們枚舉當前位的取值就很好做了……嗎?用 表示 的第 位爲 而 的第 位爲 的情況,那麼 和 是有交集的,因爲按位與的值沒有出現區別,但是 的值不一樣了。
這兩種情況怎麼處理?我們給出一個驚世駭俗的結論:二者的方案有包含關係!
首先,我們說明一下,既然在這一位上既可以取 也可以取 ,那麼取 的就一定擺脫下界;取 就一定擺脫上界。這個道理很簡單,可以取 ,那麼取 就沒有頂住下界。嚴謹證明不給出了,太簡單。
如果結論是錯誤的,那麼就有兩個不同的按位與的值,分屬於兩者。也就是:我們試圖證明 且 ,於是, 滿足 。
我們可以假設這個方案真實存在,後面的數字假設出來。對於後面某一個按位或爲 的位置(因爲按位或爲 的位置沒得選 😅),存在三種情況: 。我們都來看一看:
- 組合看圖片上面所說的, 可以更改爲 。這個數字在增大,而前面的 讓它擺脫了上界,所以不會超出範圍。
同時,第 位的選擇仍然是被固定住的。原本前面就沒法選 ,現在你又增大了一點,就更不能選 了! - 組合
類似地,將 更改爲 是完全可以的。同時,第 位的選擇也仍然沒有增多。 - 組合
仔細看完,你會發現, ,並且第 位的選擇仍然固定。
那麼,倘若真的存在兩對方案 並且二者僅僅屬於第 位的某一個選擇,那麼經過這一系列調整,將會得到 只能屬於 也只能屬於 ,矛盾。
我們已經成功除雜了,只需要使用 即可,兩種情況取最大值。
但是速度有點慢,怎麼辦呢?原來 不影響後面的轉移,影響轉移的是,是否頂住了上下界。改成四個 就行了。複雜度變成了 ,穩!
代碼
#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;
}