loj6274 數字 題解

2022-09-14 18:51:14 字數 2042 閱讀 9576

ppt

首先考慮樸素做法。我們列舉 \(v\),檢查是否能存在 \(x\) 和 \(y\) 滿足 \(x\land y=v\)。

設dp狀態 \(f[i, 0/1,0/1,0/1,0/1]\) 表示當前考慮了前 \(i\) 位,是否存在一組 \(x\) 和 \(y\),滿足 \(x\land y=v\),\(x\lor y = t\),\(lx\leq x\leq rx\),\(ly\leq y\leq ry\)。後面那四組 \(0/1\) 表示 \(x\) 和 \(y\) 是否貼著上下界。

相信各位同學也都能看出來,這就是乙個簡單的數字dp!

從高位向低位轉移即可。

**片段:

inline bool solve() }}

}}}}

for (int lx = 0; lx <= 1; ++ lx) }}

}return false;

}

現在考慮如何優化這個演算法。

我們發現每次列舉 \(v\) 的過程太耗時。於是這啟發我們思考能不能直接計算出合法 \(v\) 的數量。

對於乙個確定的 \(v\) 來說,\(f\) 陣列肯定是確定的。但如果反過來,一套確定的 \(f\) 陣列可不一定對應著唯一的 \(v\)。所以,如果我們能對於某一套 \(f\) 陣列,直接算出有多少個 \(v\) 會算出這一套 \(f\) 並累加到答案中,計算效率就會提高不少。

現在就要祭出**:dp套dp!

設外層dp狀態 \(f[i,s]\) 表示當前考慮了前 \(i\) 位,\(f[i]\) 陣列的「情況」是 \(s\),所對應的 \(v\) 的數量。

其中 \(s\) 是乙個16位二進位制數。第一位代表 \(f[i,0,0,0,0]\) 的值,第二位代表 \(f[i,0,0,0,1]\) 的值,第三位代表 \(f[i,0,0,1,0]\) 的值……以此類推。

怎麼轉移呢?

首先列舉位數 \(i\)。其次列舉 \(s\)。再其次列舉 \(v\) 的第 \(i\) 位是0還是1。然後用我們剛才提出的小 \(f\) 的轉移方法,用 \(s\) 能轉移出 \(p\) 來。最後把 \(f[i,s]\) 累加到 \(f[i-1,p]\) 中即可。

具體實現見**。這份**不開o3過不去,原因是我每次直接把 \(f\) 陣列求出來了,如果直接使用位運算會快很多。

#include #include #include using namespace std;

#define filein(s) freopen(s".in", "r", stdin);

#define fileout(s) freopen(s".out", "w", stdout)

#define mem(s, v) memset(s, v, sizeof s)

inline long long read(void)

while (ch >= '0' && ch <= '9')

return f * x;

}const int maxn = 63;

bool f[2][2][2][2], g[2][2][2][2];

char t[maxn], lx[maxn], rx[maxn], ly[maxn], ry[maxn];

long long f[maxn][70000];

inline void change(long long x, char str)

}inline int call(int s, int i)

inline int get(int i, int st, int v) }}

}}

}cnt = 0;

int res = 0;

for (int lx = 0; lx <= 1; ++ lx) }}

}return res;

}int main() }}

long long ans = 0;

for (int s = 1; s < (1 << 16); ++ s) ans += f[1][s];

printf("%lld\n", ans);

return 0;

}

LOJ 6274 數字 數字dp

題目描述 nirobc 姐姐腦洞了兩個數字 和 它們滿足 且 nirobc 姐姐想知道 有多少種不同的取值,若有多組 的 值相同,則只算一次。其中 表示按位取或,c c 中寫作 pascal中寫作or 其中 表示按位取與,c c 中寫作 pascal中寫作and 輸入格式 一行,五個非負整數 輸出格...

題解 LOJ540遊戲

小l計畫進行n場遊戲,每場遊戲使用一張地圖,小 l 會同時使用三輛車在該地圖上完成遊戲。小 l 的賽車有三輛,分別用大寫字母 a b c 表示。地圖是一張無向簡單圖 沒有重邊或自環 每次他會在地圖中選擇不同的三個點 i,j,k滿足 i且兩兩之間均有邊。此時他會讓 a 從i到j,b 從j到k,c從k到...

題解 Loj2727舞會

n 個數,其中有 m 個位置的數是確定的,另外的數隨意排列。每次操作把最前面三個數取出,把它們的中位數取出來放到最後,然後刪掉這三個數。通過合適的排列,使最後留下來的數最大。首先這類有關中位數的問題,可以二分後轉化為操作 01 序列的問題。每次二分乙個有可能的答案 mid 把 mid 換成一,的數換...