AtCoder Regular Contest 141 - B - Increasing Prefix XOR
原文
Consider the problem in binary.
If positive integers \(a\) and \(b\) have the same number of digits, the only case when both \(a<c\) and \(b < b\oplus c\) hold is when \(c\) has more digits than each of \(a\) and \(b\), in which case \(c\) and \(b \oplus c\) have the same number of digits.
From this, it can be inductively shown that when \(A\)
Therefore, when \(M < 2^{60}\), the answer is \(0\) if \(60 < N\). Otherwise, let us precompute the number of \(k\)
\(dp[n][k]:\) the number of sequences \((A_1,\ A_2,\ \dots,\ A_n)\) of positive integers with increasing numbers of digits whose \(A_n\) has \(k\) digits.
(Alternatively, consider taking at most one \(k\)
Therefore, the problem can be solved in \(O(\log^3{M})\) or \(O(\log^2 {M})\) time.
解釋:
我們從二進位制的角度來解決這個問題。
如果兩個正整數a,b在二進位制下有相同的位數,若希望\(a<c\) 和 \(b < b\oplus c\) 均成立,只有\(c\)的位數比\(a,b\)都多才能滿足。在這種情況下,\(c\) 和 \(b \oplus c\) 的位數是相同的。
換句話說,若\(a<c\) 和 \(b < b\oplus c\) 均成立,則必有\(c\)的位數比\(a,b\)都多(注意前提條件,a,b的位數相同)。
為什麼呢?
從右式出發,顯然c的位數不可能小於b,假設c的位數和b相同,均為\(n\)。
顯然它們的最高位必然均為1,則異或的結果的位數必然小於\(n\),故\(b > b \oplus c\),與原條件矛盾,故假設不成立。
故\(c\)的位數大於\(a,b\)的位數
由此,當序列\(A\)滿足條件時,有\(A_{i+1}\)的位數多於\(A_i\)。另一方面,如果\(A_{i+1}\)的位數均大於\(A_i\),則顯然能滿足條件。
這裡相當於令上文的\(a = A_i, b = B_i, c = A_{i + 1}\)
需要補充說明:
- 原條件:\(B_1<B_2<⋯<B_N, \text {where } B_i = A_1 \oplus A_2 \oplus \dots \oplus A_i.\)
- \(B_i的位數 = A_i的位數,即b = a\) 的必要條件是\(A_{i+1}\)的位數均大於\(A_i\)
- \(B_{i + 1}= B_i \oplus A_{i+ 1}\)
- \(A_i = B_i\oplus A_1 \oplus A_2 \oplus ...\oplus A_{i - 1}\)
因此,當\(M<2^{60}\)時,如果\(N > 60\),答案就是\(0\)。
\(A_i\)的位數是單調遞增的,若\(N > 60\),則必存在\(A_i,A_i\)的位數\(>60\),而條件限制\(A_i\le M\),顯然有矛盾,故答案為0
否則,讓我們預先計算\(1\)到\(M\)之間的長度為\(k\)(二進位制下)的整數的個數,通過動態規劃在\(O(Nlog^2 M)\)的時間內解決這個問題,其中我們設定
\(dp[n][k]:\)由位數單調遞增的正整陣列成的,長度為n的序列\((A_1,\ A_2,\ \dots,\ A_n)\)構成的集合的元素個數,且其中\(A_n\)有\(k\)位數。
\(dp(n, k) = cnt[k]* \sum_{j=1}^{k-1}dp(i-1, j)\),其中
cnt[k]
為位數為k
的整數的數量
(或者,考慮在每一個\(k\)中最多取一個\(k\)位數的整數,總共選擇\(N\)次,以\(O(N\log M)\)的時間來解決。)
Alternatively, consider taking at most one \(k\)-digit integer for each \(k\) to choose \(N\) in total, to solve it in \(O(N \log M)\) time.
這裡實在看不太明白==
因此,這個問題可以在\(O(\log^3{M})\)或\(O(\log^2 {M})\)時間內解決。
程式碼
// Problem: B - Increasing Prefix XOR
// Contest: AtCoder - AtCoder Regular Contest 141
// URL: https://atcoder.jp/contests/arc141/tasks/arc141_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 61, mod = 998244353;
typedef long long LL;
LL n, m, ans;
int f[N][N];
LL cnt[N];
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
int size = 0;
LL t = m;
while (t){
size ++ ;
t >>= 1;
}
for (int i = 1; i <= 60; i ++ ){ // cnt[i]表示位數為 i 的,不超過 m 的整數的個數
if (i < size) cnt[i] = 1ll << (i - 1);
if (i == size) cnt[i] = m + 1 - (1ll << (i - 1));
if (i > size) break;
f[1][i] = cnt[i];
}
if (n > 60){
cout << "0" << endl;
return 0;
}
for (int i = 2; i <= n; i ++ ){ // 長度
for (int j = 1; j <= size; j ++ ){ // A_n的位數
for (int k = 1; k < j; k ++ ){ // A_(n-1)的位數
f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
}
f[i][j] = cnt[j] % mod * f[i][j] % mod;
}
}
for (int i = 0; i <= 60; i ++ ) ans = (ans + f[n][i]) % mod;
cout << ans << endl;
return 0;
}
疑惑
我想用字首和優化一維,但是改來改去還是wa:(