【清华集训2014】玛里苟斯

看到这道题,然后便错误地联想到了数位DP什么的……接着发现了答案在一个界内,然后就想着暴力了。

首先如果对每一位都设一个变量的话,根据插板法,最多只能有1e7个项对答案有贡献,和答案在一个界内这个条件组合起来,这启发我们去想暴力。

首先非基变量是没有用的,考虑它们的选和不选,最后都要除掉。

所以只有基变量有贡献。

显然基变量越多跑的越慢,这个时候设基变量有 \(b\) 个,很明显可以得到答案的一个粗略的下界

\[\frac{\sum_{i=0}^{2^{b-1}} i^k}{2^{b-1}} \]

首先上面是一个自然幂数前缀和,显然是一个 \(k+1\) 项的多项式,忽略常数带来的影响,除掉分母,令 \(x = 2^b\),可得

\[x ^ k \le 2^{63} \]

也就是说,$ b \leq \log_2 \sqrt[k]{2^{63}} $,易得 \(k \geq 3\) 的时候是可以暴力枚举基的。

那么只剩下 \(k = 1\)\(2\) 了。

考虑 \(k = 1\),只要按位考虑贡献即可。

考虑 \(k = 2\),对于平方,只是同一种方案对每两个位的值进行乘积后求和。所以需要同时考虑两位。

因为单个变量 \(0\)\(1\) 是相同的,所以考虑分别乘个 \(\frac{1}{2}\) 即可。

拆一下式子枚举变量即可。注意 \(k = 2\) 时只有 \(\frac{1}{2}\) 的判定不是下标相同(虽然式子拆出来是这样的),而是在基张成的线性空间里每个向量这两位都相同。即基向量矩阵中这两行相等。

计算过程可以用 __int128 所以没什么问题,long double 会掉精度。

所以还是一道简单题,但我还是爆OJ了。

#include <bits/stdc++.h>

typedef unsigned long long LL;
typedef __int128 H;
LL lb[64], bss[64], mat[64];
int n, K, bak;
void insert(LL v) {
	for (int i = 63; ~i; --i)
		if (v >> i & 1) {
			if (lb[i]) v ^= lb[i];
			else { lb[i] = v; break; }
		}
}
LL fnd(LL x) {
	LL res = 0;
	for (int i = 63; ~i; --i)
		if (lb[i] & x)
			res |= 1llu << i;
	return res;
}
H fastpow(H a, int px) {
	H res = 1;
	while (px --> 0) res *= a;
	return res;
}
H haans;
void dfs(int now, LL v) {
	if (now == bak) {
		haans += fastpow(v, K);
		return ;
	}
	dfs(now + 1, v);
	dfs(now + 1, v ^ bss[now]);
}
int main() {
	std::ios_base::sync_with_stdio(false), std::cin.tie(0);
	std::cin >> n >> K;
	LL t;
	for (int i = 1; i <= n; ++i) std::cin >> t, insert(t);
	for (int i = 0; i < 64; ++i) if (lb[i]) bss[bak++] = lb[i];
	H ans = 0; LL app = 0;
	for (int i = 0; i != 64; ++i) app |= lb[i];
	if (K >= 3) dfs(0, 0), ans = haans >> bak - 1;
	else if (K == 2) {
		for (int i = 0; i != 64; ++i) mat[i] = fnd(1llu << i);
		for (int i = 0; i != 64; ++i) if (app >> i & 1)
			for (int j = 0; j != 64; ++j) if (app >> j & 1)
				ans += (H) (1llu << i) * (1llu << j) * (1 << (mat[i] == mat[j]));
		ans >>= 1;
	} else ans = app;
	LL ax = ans;
	std::cout << (ax >> 1);
	if (ax & 1) std::cout << ".5";
	std::cout << std::endl;
	return 0;
}
posted @ 2019-09-12 23:21  daklqw  阅读(370)  评论(0编辑  收藏  举报