zoukankan      html  css  js  c++  java
  • loj6358. 前夕

    题意

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

    题解

    广义容斥 + 构造好题。
    (g(x))表示取出的集合交集数恰好为(x)的方案数,(f(x))表示钦定(x)个集合一定要取的方案数。
    显然,(f(x) = inom{n}{x} (2 ^ {2 ^ {n - x}} - 1)),然后(g(x))(f(x))的关系可以用二项式反演求出,即

    [g(k) = sum_{i = k} ^ n {(-1)} ^ {i - k} inom{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])

    [egin{aligned} Ans & = sum_{k = 0} ^ n [4 | k] sum_{i = k} ^ n {(-1)} ^ {i - k} inom{i}{k} f(i) \ & = sum_{i = 0} ^ n f(i) sum_{k = 0} ^ i {(-1)} ^ {i - k} inom{i}{k} [4|k] \ end{aligned} ]

    则得出

    [a(i) = sum_{k = 0} ^ i {(-1)} ^ {i - k} inom{i}{k} [4|k] \ ]

    可是还不够,继续。
    对于([4|k]),用单位根反演,即

    [[4|k] = frac{1}{4} sum_{i = 0} ^ 3 omega_4 ^ {ik} ]

    [egin{aligned} a(i) & = sum_{k = 0} ^ i {(-1)} ^ {i - k} inom{i}{k} frac{1}{4} sum_{l = 0} ^ 3 omega_4 ^ {lk} \ & = frac{{(-1)} ^ i}{4} sum_{k = 0} ^ i {(-1)} ^ k inom{i}{k} sum_{l = 0} ^ 3 ({omega_4 ^ l}) ^ k \ & = frac{{(-1)} ^ i}{4} sum_{l = 0} ^ 3 sum_{k = 0} ^ i inom{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 inom{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;
    }
    
  • 相关阅读:
    机器学习 深度学习 计算机视觉 资料汇总
    激活层和pooling的作用
    NVIDIA GPU 计算能力
    TX2 刷机过程
    Anaconda tensorflow 安装笔记
    yolo-开源数据集coco kitti voc
    TX2上yolov3精度和速度优化方向
    yolo原理学习
    ubuntu常用命令
    tensorflow mnist模块详解
  • 原文地址:https://www.cnblogs.com/psimonw/p/11456746.html
Copyright © 2011-2022 走看看