:::info[Description] Link. :::
:::infoSolution 集合幂级数入门题,但是我咋不会做。
首先由经典结论:,因此题目要求的式子 。
考虑解决更通用的问题,记 ,则考虑提取 则有 ,继续推导拆掉 后可得 ,交换球和顺序可得 。
然后式子的两个部分可以分别计算。具体的:
- 可以看作是对 数组做子集和。
- 可以看作是对 的超集做差分。
- 答案就是对应位置相乘后得到的超集和 。
然后这个东西做两遍就可以把题目要求出的式子求出来,总时间复杂度为 可以通过该题。 :::
:::success[Code]
namespace lowspeed_song {
inline void init() {
}
int n, k, a[N];
inline vector<int> gao(vector<int> f, vector<int> g) {
for (int i = 0; i < k; ++i)
for (int j = 0; j < (1 << k); ++j)
if (j >> i & 1) f[j] = (f[j] + f[j ^ (1 << i)]) % mod;
for (int i = 0; i < k; ++i)
for (int j = 0; j < (1 << k); ++j)
if (~j >> i & 1) g[j] = (g[j] - g[j | (1 << i)] + mod) % mod;
for (int i = 0; i < (1 << k); ++i) f[i] = f[i] * g[i] % mod;
for (int i = 0; i < k; ++i)
for (int j = 0; j < (1 << k); ++j)
if (~j >> i & 1) f[j] = (f[j] + f[j | (1 << i)]) % mod;
return f;
}
inline void sol() {
cin >> n >> k;
vector<int> cnt(1 << k), sum(1 << k), g(1 << k);
for (int i = 0; i < n; ++i) cin >> a[i], ++cnt[a[i]];
for (int i = 1; i < (1 << k); ++i) {
int bit = __builtin_popcount(i);
sum[i] = cnt[i] * bit % mod, g[i] = inversion(bit);
} vector<int> A = gao(cnt, g), B = gao(sum, g);
for (int i = 0; i < n; ++i) cout << (A[a[i]] * __builtin_popcount(a[i]) % mod + B[a[i]] + mod - n) % mod << '\n';
}
} // namespace lowspeed_song:::
难度:紫+
鲜活指数:7
喜欢的话,留下你的评论吧~