题解 P3214 【[HNOI2011]卡农】

qwaszx

2020-09-24 19:32:01

Solution

~~还是科技好用,不动脑子还复杂度优秀~~ 题意相当于是在 $1\cdots n$ 的非空子集中选出 $m$ 个互不相同的,满足这些集合异或起来为空,那么可以按照题意直接写出生成函数: $$ F(x,t)=\prod_{S\neq \varnothing}(1+x^St) $$ 我们要求的就是 $[x^{\varnothing}t^m]F$ 处理集合幂级数自然考虑 FWT(或者说高维 DFT),那么考虑施加 DFT 后 $T$ 位置上变成了什么,只需对每个 $1+x^St$ 进行 DFT 后乘起来即可. 那么答案就是 $$ \prod_{S\neq \varnothing}(1+(-1)^{|S\cap T|}t) $$ $(-1)^{|S\cap T|}$ 的不同取值只有两种,我们可以分别计数每种情况出现了多少次. 只考虑 $|S\cap T|$ 为偶数的情况,奇数可以简单地用 $2^n-1$ 来减. $$ \sum_i\sum_{S\neq \varnothing}[|S\cap T|=2i]=\sum_i 2^{n-|T|}\binom{|T|}{2i}-1 $$ 当 $|T|\neq 0$ 时,我们知道 $$ \sum_i\binom{|T|}{2i}=\sum_i\binom{|T|}{2i+1}=2^{|T|-1} $$ 这就给出 $$ \prod_{S\neq \varnothing}(1+(-1)^{|S\cap T|}t)=(1+t)^{2^{n-1}-1}(1-t)^{2^{n-1}} $$ 而 $|T|=0$ 时答案是平凡的: $$ (1+t)^{2^n-1} $$ 再逆变换回去,有 $$ [x^{T}]F=\frac{1}{2^n}\sum_S (-1)^{|S\cap T|}[x^S]DFT(F) $$ 在这道题上就是 $$ [x^{\varnothing}t^m]F=\frac{1}{2^n}[t^m]\sum_S[x^S]DFT(F)=\frac{1}{2^n}[t^m]\left((1+t)^{2^n-1}+(2^n-1)(1+t)^{2^{n-1}-1}(1-t)^{2^{n-1}}\right) $$ 前面一项显然就是$\dbinom{2^n-1}{m}$,后面一项可以改写为 $(1-t)(1-t^2)^{2^{n-1}-1}$,按照 $m$ 的奇偶性讨论后可以写为 $(-1)^{\lceil m/2\rceil}\dbinom{2^{n-1}-1}{\lfloor m/2\rfloor}$. 于是问题在于组合数的计算,朴素实现即可 $O(m)$ 完成,存在更加快速的方法(或分块打表阶乘及逆元). ```cpp #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1e6+500,mod=100000007; int ifac[N],n,m; int qpower(int a,int b){int ans=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;} int C(int n,int m) { if(n<m)return 0; int ans=ifac[m]; for(int i=0;i<m;i++)ans=1ll*ans*(n-i)%mod; return ans; } int main() { scanf("%d%d",&n,&m);int pw=qpower(2,n-1); ifac[0]=ifac[1]=1;for(int i=2;i<=m;i++)ifac[i]=1ll*(mod-mod/i)*ifac[mod%i]%mod; for(int i=2;i<=m;i++)ifac[i]=1ll*ifac[i-1]*ifac[i]%mod; int ans=0; if(m&1)ans+=(((m+1)>>1&1)?-1:1)*C(pw-1,(m-1)>>1); else ans+=((m>>1&1)?-1:1)*C(pw-1,m>>1); ans=(1ll*ans*(2*pw-1)+C(2*pw-1,m))%mod; ans=1ll*ans*qpower(2*pw,mod-2)%mod; cout<<(ans+mod)%mod<<endl; } ```