码迷,mamicode.com
首页 > 其他好文 > 详细

loj6358. 前夕

时间:2019-09-04 09:29:50      阅读:74      评论:0      收藏:0      [点我收藏+]

标签:mat   splay   就是   ace   ali   names   span   取出   复杂度   

题意

\(X = \{1, 2, \dots, n\}\)\(S = 2 ^ X\),求从\(S\)中取出一些集合(可不取),其交集为4的倍数的方案数。
\(n \leq {10} ^ 7\)

题解

广义容斥 + 构造好题。
\(g(x)\)表示取出的集合交集数恰好为\(x\)的方案数,\(f(x)\)表示钦定\(x\)个集合一定要取的方案数。
显然,\(f(x) = \binom{n}{x} (2 ^ {2 ^ {n - x}} - 1)\),然后\(g(x)\)\(f(x)\)的关系可以用二项式反演求出,即
\[ g(k) = \sum_{i = k} ^ n {(-1)} ^ {i - k} \binom{i}{k} f(i) \]
但是二项式反演所有求\(g(x)\)\(O(n ^ 2)\)的复杂度。
考虑一种巧妙的构造。
\(Ans = \sum_{i = 0} ^ n f(i) a(i)\)
由于显然有\(Ans = \sum_{i = 0} ^ n g(i) b(i)\),其中\(b(i) = [4 | i]\)

\[ \begin{aligned} Ans & = \sum_{k = 0} ^ n [4 | k] \sum_{i = k} ^ n {(-1)} ^ {i - k} \binom{i}{k} f(i) \& = \sum_{i = 0} ^ n f(i) \sum_{k = 0} ^ i {(-1)} ^ {i - k} \binom{i}{k} [4|k] \\end{aligned} \]
则得出
\[ a(i) = \sum_{k = 0} ^ i {(-1)} ^ {i - k} \binom{i}{k} [4|k] \\]
可是还不够,继续。
对于\([4|k]\),用单位根反演,即
\[ [4|k] = \frac{1}{4} \sum_{i = 0} ^ 3 \omega_4 ^ {ik} \]

\[ \begin{aligned} a(i) & = \sum_{k = 0} ^ i {(-1)} ^ {i - k} \binom{i}{k} \frac{1}{4} \sum_{l = 0} ^ 3 \omega_4 ^ {lk} \& = \frac{{(-1)} ^ i}{4} \sum_{k = 0} ^ i {(-1)} ^ k \binom{i}{k} \sum_{l = 0} ^ 3 ({\omega_4 ^ l}) ^ k \& = \frac{{(-1)} ^ i}{4} \sum_{l = 0} ^ 3 \sum_{k = 0} ^ i \binom{i}{k} {(-1)} ^ k ({\omega_4 ^ l}) ^ k \& = \frac{{(-1)} ^ i}{4} \sum_{l = 0} ^ 3 (1 - {\omega_4 ^ l}) ^ i \\end{aligned} \]
然后这个东西就比较容易了。
直接计算
\[ Ans = 1 + \sum_{i = 0} ^ n \binom{n}{i} (2 ^ {2 ^ {n - i}} - 1) \cdot \frac{{(-1)} ^ i}{4} \sum_{l = 0} ^ 3 (1 - {\omega_4 ^ l}) ^ i \]
这个1就是所有集合都不选的方案(注意到它在\(f(0)\)中被除去了)。
处理过程中,是可以用一些技巧,避免使用快速幂的。
所以这个复杂度就是\(\mathcal O(n)\)的,常数为4(实际肯定比这个大很多)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int power (int a, int b, int mod) {
    int ret = 1;
    for ( ; b; b >>= 1, a = 1ll * a * a % mod) {
        if (b & 1) {
            ret = 1ll * ret * a % mod;
        }
    }
    return ret;
}

const int N = 1e7 + 3, mod = 998244353;
const int omega = 911660635, inv4 = 748683265;
int n, ans, f, a, w, r[4], s[4];
int fac[N], ivf[N], po[N], pw[N], pn[N];
int C (int p, int q) {
    return 1ll * fac[p] * ivf[q] % mod * ivf[p - q] % mod;
}
void prework () {
    fac[0] = ivf[0] = 1;
    for (int i = 1; i < N; ++i) {
        fac[i] = 1ll * fac[i - 1] * i % mod;
    }
    ivf[N - 1] = power(fac[N - 1], mod - 2, mod);
    for (int i = N - 2; i; --i) {
        ivf[i] = 1ll * ivf[i + 1] * (i + 1) % mod;
    }
    po[0] = 2;
    for (int i = 1; i < N; ++i) {
        po[i] = 1ll * po[i - 1] * po[i - 1] % mod;
    }
    w = 1;
    for (int i = 0; i < 4; ++i) {
        r[i] = (1 - w + mod) % mod;
        s[i] = 1;
        w = 1ll * w * omega % mod;
    }
}
int main () {
    prework();
    cin >> n;
    for (int i = 0; i <= n; ++i) {
        f = 1ll * C(n, i) * (po[n - i] - 1 + mod) % mod;
        a = 0;
        for (int k = 0; k < 4; ++k) {
            a = (a + s[k]) % mod;
            s[k] = 1ll * s[k] * r[k] % mod;
        }
        a = 1ll * a * inv4 % mod;
        a = i & 1 ? mod - a : a;
        ans = (1ll * f * a + ans) % mod;
    }
    cout << (ans + 1) % mod << endl;
    return 0;
}

loj6358. 前夕

标签:mat   splay   就是   ace   ali   names   span   取出   复杂度   

原文地址:https://www.cnblogs.com/psimonw/p/11456746.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!