zoukankan      html  css  js  c++  java
  • #4307. 前夕

    题目描述

    为了抵御以尼古拉奥尔丁为首的上古龙族的入侵,地球的守护者 Yopilla 集齐了 $n$ 种人类文明的本源力量 —— 世界之力。

    Yopilla 打算使用若干种技能来对抗尼古拉奥尔丁的进攻。每种技能由若干种世界之力构成。换句话说,一共有 $2 ^ n$ 种技能,Yopilla 要使用若干种技能来对抗尼古拉奥尔丁。

    大战前夕,Yopilla 走在波士顿的街头,突然看见天空中飞过了 $4$ 只白鸽,他便洞察了战胜尼古拉奥尔丁的秘密:只要他使用的技能中,都含有的世界之力的种类数恰好为 $4$ 的倍数,他便可以打败敌人。

    Yopilla 想知道,他有多少种使用技能的情况,能战胜敌人。请你替 Yopilla 回答这个问题,答案对 $998244353$ 取模即可。

    题解

    好仙的题啊

    考虑设交集大小至少为 $x$ 的个数为 $a_x$ ,则 $a_x=(_x^n)(2^{2^{n-x}}-1)$

    然后我们考虑构造容斥系数 $f_x$ ,使得 $ans=sum_{x=0}^nf_xa_x$

    然后我们考虑到如果交集大小恰好为 $x$ 的最终要被算 $[x\%4=0]$ 遍,而对于 $le x$ 的 $i$ ,它对于 $x$ 的贡献就是 $(_i^x)$ ,所以我们要使得 $[x\%4=0]=sum_{k=0}^x(_k^x)f_x$

    考虑二项式反演,将式子化为 $f_x=sum_{k=0}^x(-1)^{x-k}(_k^x)[x\%4=0]$

    考虑将 $[x\%4=0]$ 化开,这时候我们要用到很神奇的东西:单位复数根

    记 $w_m$ 表示主 $m$ 次单位根,那么根据性质,我们可以得到 $[x\%m=0]=sum_{i=0}^{m-1}(w_m^x)^i$

    于是 $f_x=sum_{k=0}^x(-1)^{x-k}(_k^x)sum_{i=0}^{4-1}(w_4^x)^i$

    把 $i$ 提前,得到 $f_x=frac{(-1)^x}{4}sum_{i=0}^{3}(1-w_4^i)^x$

    于是我们可以 $O(nm)$处理出 $f_x$ ,然后计算答案

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e7+5,P=998244353;
    int n,jc[N],ny[N],w[4],W[4],f[N],s=1;
    int X(int x){return x>=P?x-P:x;}
    int C(int x,int y){
        return 1ll*jc[x]*ny[y]%P*ny[x-y]%P;
    }
    int K(int x,int y){
        int z=1;
        for (;y;y>>=1,x=1ll*x*x%P)
            if (y&1) z=1ll*z*x%P;
        return z;
    }
    int main(){
        cin>>n;jc[0]=1;
        for (int i=1;i<=n;i++)
            jc[i]=1ll*i*jc[i-1]%P;
        ny[n]=K(jc[n],P-2);
        for (int i=n;i;i--)
            ny[i-1]=1ll*i*ny[i]%P;
        w[0]=1;w[1]=911660635;
        for (int i=2;i<4;i++)
            w[i]=1ll*w[i-1]*w[1]%P;
        for (int i=0;i<4;i++)
            W[i]=1,w[i]=X(1+P-w[i]);
        for (int i=0,F=1;i<=n;i++,F=P-F){
            for (int j=0;j<4;j++)
                f[i]=X(f[i]+W[j]);
            f[i]=748683265ll*F%P*f[i]%P;
            for (int j=0;j<4;j++)
                W[j]=1ll*W[j]*w[j]%P;
        }
        for (int i=n,v=2,u;~i;i--)
            u=1ll*C(n,i)*X(v-1+P)%P,
            s=X(s+1ll*u*f[i]%P),v=1ll*v*v%P;
        cout<<s<<endl;return 0;
    }
  • 相关阅读:
    Python开发环境搭建
    Python逻辑判断顺序
    PyCharm快捷改变字体大小
    Python类型转换
    前端面试总结2020
    问题总结20-11-02至20-11-09
    问题总结20-11-30至20-12-06
    项目管理培训20-12-06
    日期计算
    数列分段
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12285481.html
Copyright © 2011-2022 走看看