[组合计数] [信息论] CF643F Bears and Juice
posted on 2025-03-31 10:45:15 | under | source
题意:\(n\) 只熊,\(p\) 个床,\(m\) 个木桶,恰有一桶酒。每天每只醒的熊可以选择若干木桶品尝,假如喝到了酒就躺床上睡了,床不够则游戏结束。记 \(q_i\) 表示令第 \(i\) 天后,醒着的熊一定可猜出酒在哪的情况下,\(m\) 最大为多少。对 \(i\in [1,q]\),求 \(\oplus i\times q_i\)。\(n\le 10^9\),\(p\le 130\),\(q\le 2\times 10^6\)。
第 \(i\) 天后,可以得到的信息只有每只熊是否睡了、在哪一天睡。相同信息能推出的结果一定相同。可分辨的信息种类为:
\[\sum\limits_{j=0}^{\min(n-1,p)} {{n}\choose{j}}i^j
\]
含义即为选择睡下的熊以及日期。
猜测答案即为上界。考虑构造一种方案,不妨令第 \(k\) 条信息直接对应第 \(k\) 桶酒(酒之间没有区别),每头熊假如在第 \(k\) 条信息中睡下了,就只在睡下的那一天品尝这个酒;否则不品尝。这样信息和酒一一对应。
预处理组合数时暴力消分号上下公因数即可。\(O(p^3\log p+pq)\)。
代码
#include<bits/stdc++.h>
using namespace std;
#define ui unsigned int
const int N = 2e2 + 5;
int n, p, q, a[N], b[N];
ui C[N];
inline ui cc(int x){
for(int i = 1; i <= x; ++i) a[i] = n - i + 1, b[i] = i;
for(int i = 1; i <= x; ++i)
for(int j = 1; j <= x; ++j){
int d = __gcd(a[i], b[j]);
a[i] /= d, b[j] /= d;
}
ui res = 1;
for(int i = 1; i <= x; ++i) res *= a[i];
return res;
}
signed main(){
cin >> n >> p >> q;
for(int i = 0; i <= min(n - 1, p); ++i) C[i] = cc(i);
ui ans = 0;
for(int i = 1; i <= q; ++i){
ui res = 0, pw = 1;
for(int j = 0; j <= min(n - 1, p); ++j, pw *= i) res += C[j] * pw;
ans ^= res * i;
}
cout << ans;
return 0;
}

浙公网安备 33010602011771号