LOJ 前夕
解题方法:
设F(x)表示至少有i种技能的方案数
显然有:$F(x)=C_{n}^{x} \times 2^{2^{n-x}}$
我们构造容斥函数$f(x)$,令$Ans=\sum f(x) \times F(x)$
题目要求的是所有技能数恰为4k的方案数,所以能得出$[4|x]=\sum\limits_{i=0}^{x} C_{x}^{i}*f[i]$
二项式反演得:$f[x]=\sum\limits_{i=0}^{x} (-1)^{x-i} \times C_{x}^{i}*[4|i]$
$[4|i]$这个东西是可以转化成单位根的式子的,$[4|i]=\frac{1}{4}\sum\limits_{j=0}^{3}\omega^{ij}$
带进去:$f[x]=\frac{1}{4}\sum\limits_{i=0}^{x} (-1)^{x-i} \times C_{x}^{i} \sum\limits_{j=0}^{3} \omega^{ij}$
$=\frac{1}{4}\sum\limits_{j=0}^{3} \sum\limits_{i=0}^{x} (-1)^{x-i} \times C_{x}^{i} \omega^{ij}$
$=\frac{1}{4}\sum\limits_{j=0}^{3}(\omega^{j}-1)^{x}$
我们成功的求出了容斥函数
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) #define dwn(i,a,b) for(int i=a;i>=b;i--) #define MAXN 10000005 using namespace std; int read(){ int x=0,f=1; char ch=getchar(); while(ch>'9' || ch<'0') ch=getchar(); while('0'<=ch && ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); return x; } typedef long long ll; const ll mod=998244353; int n; ll ksm(ll x,ll y){ ll res=1; while(y){ if(y&1) res=(res*x)%mod; x=(x*x)%mod; y>>=1; } return res; } ll jc=1,ans,inv1=mod-1,a[MAXN],F,now=1,sum,tmp,inv[MAXN],Wn[4],w[4],inv4,f; void pd(){ if(tmp==1) tmp=inv1; else tmp=1; } ll C(ll x,ll y){ return (jc*inv[x]%mod)*inv[y-x]%mod; } int main(){ n=read(); inv[1]=1; inv[0]=1; inv4=ksm(4,mod-2); a[n]=2; w[0]=w[1]=w[2]=w[3]=1; rep(i,2,n) inv[i]=((-(mod/i)*inv[mod%i])%mod+mod)%mod,jc=(jc*i)%mod; rep(i,2,n) inv[i]=inv[i-1]*inv[i]%mod; Wn[0]=0; Wn[1]=ksm(3,(mod-1)/4)-1; Wn[2]=ksm(3,(mod-1)/2)-1; Wn[3]=ksm(3,((mod-1)/4)*3)-1; dwn(i,n-1,0) a[i]=(a[i+1]*a[i+1])%mod; rep(i,0,n) a[i]=(a[i]-1+mod)%mod; rep(i,0,n){ F=a[i]*C(i,n)%mod; f=inv4*((w[0]+w[1]+w[2]+w[3])%mod)%mod; ans=(ans+F*f)%mod; rep(j,0,3) w[j]=(w[j]*Wn[j])%mod;//,cout<<w[j]<<" ";cout<<endl; } printf("%lld",(ans+1)%mod); return 0; }