[组合计数] [信息论] 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;
}

posted @ 2026-01-13 11:26  Zwi  阅读(0)  评论(0)    收藏  举报