• FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅲ


    第三波,走起~~

    FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ

    FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ

    单位根反演

    今天打多校时 1002 被卡科技了……赛场上看出来是个单位根反演但不会,所以只好现学这东西了(

    首先你得知道单位根是什么东西,对于 (n) 次方程 (x^n-1=0(xinmathbb{C})),在复数域上有 (n) 个根,其对应到复平面上就是单位圆的 (n) 等分点,我们将这些单位根从 (x) 轴正半轴开始顺时针依次标号 (0,1,2,cdots,n-1),记作 (omega_n^0,omega_n^1,omega_n^2,cdots,omega_n^{n-1}),显然单位根满足以下性质:

    • (omega_n^x=cosdfrac{2pi x}{n}+sindfrac{2pi x}{n} ext{i})
    • ((omega_n^x)^n=1)
    • (omega_n^x=(omega_n^1)^x)

    相信学过 FFT 的同学都不难理解。

    单位根反演说的大概是这样一件事,对于任意整数 (n)(x),有 ([nmid x]=dfrac{1}{n}sumlimits_{i=0}^{n-1}(omega_n^{x})^i)。也就是说如果 (x)(n) 的倍数那么 (dfrac{1}{n}sumlimits_{i=0}^{n-1}(omega_n^{x})^i=1),否则 (dfrac{1}{n}sumlimits_{i=0}^{n-1}(omega_n^{x})^i=0)

    证明:

    • 如果 (nmid x),那么显然 (omega_n^x=1)(sumlimits_{i=0}^{n-1}(omega_n^x)^i=n)
    • 如果 (n mid x),那么根据等比数列求和公式 (sumlimits_{i=0}^{n-1}(omega_n^{x})^i=dfrac{(omega_n^x)^n-1}{omega_n^x-1}),显然分子等于 (0),而由于 (n mid x)(omega_n^x-1 e 0),因此分式值为 (0)

    那么什么样的题能用单位根反演呢?首先如果题目给你一个带组合数的式子,这个组合数中带有取模符号 (mod),而往往这个组合数上底数非常大(高达 (10^9) 甚至 (10^{18})),而下底数中含枚举变量,那么此时这道题大概率就是单位根反演,运用二项式定理将组合数转化为幂的形式求解。注意,这里的 (mod y) 后面的 (y) 应当在输入中确定了,如果 (y) 作为枚举变量则无法二项式定理,还有一般单位根反演的题都涉及到取模,如果 (y mid MOD-1) 那么也无法二项式反演,因为我们要通过 (g^{(MOD-1)/y}) 求出 (omega_y^1mod MOD)(譬如前天晚上的 D1C 如果模数 (=10^9+9) 就可以单位根反演了?)

    说了这么多,还是具体题目具体分析吧。

    60. LOJ #6485. LJJ 学二项式定理

    首先这题组合数的 (n) 非常大,直接算的话第一步就爆了,因此我们需要想着用二项式定理将这里的 (n) 放到指数上去,怎么办呢?注意到这里涉及到 (mod 4),而刚好有 (4mid 998244352),因此可以考虑单位根反演,上来推一波式子:

    [egin{aligned} ans&=sumlimits_{i=0}^ndbinom{n}{i}s^isumlimits_{j=0}^3a_j[jequiv ipmod 4]\ &=sumlimits_{j=0}^3a_jsumlimits_{i=0}^ndbinom{n}{i}s^i[4mid(i-j)]\ &=sumlimits_{j=0}^3a_jsumlimits_{i=0}^ndbinom{n}{i}s^isumlimits_{k=0}^3omega_4^{(i-j)k}·dfrac{1}{4}\ &=dfrac{1}{4}sumlimits_{j=0}^3a_jsumlimits_{k=0}^3dfrac{1}{omega_4^{jk}}sumlimits_{i=0}^ndbinom{n}{i}s^iomega_4^{ik}\ &=dfrac{1}{4}sumlimits_{j=0}^3a_jsumlimits_{k=0}^3dfrac{1}{omega_4^{jk}}(somega_4^k+1)^n end{aligned} ]

    然后直接计算就行了,众所周知 (998244353) 的一个原根 (g=3),那么我们可以通过 (g^{998244352/4}) 求出 (omega_4^1)

    const int MOD=998244353;
    const int INV4=(3ll*MOD+1)>>2;
    int w[4];
    int qpow(int x,int e){
    	int ret=1;
    	for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
    	return ret;
    }
    ll n;int s,a[4];
    void solve(){
    	int res=0;scanf("%lld%d%d%d%d%d",&n,&s,&a[0],&a[1],&a[2],&a[3]);n%=(MOD-1);
    	for(int i=0;i<4;i++) for(int j=0;j<4;j++)
    		res=(res+1ll*a[i]*w[(16-j*i)&3]%MOD*qpow((1ll*w[j]*s+1)%MOD,n))%MOD;
    	printf("%d
    ",1ll*res*INV4%MOD);
    }
    int main(){
    	w[0]=1;w[1]=qpow(3,MOD-1>>2);w[2]=1ll*w[1]*w[1]%MOD;
    	w[3]=1ll*w[1]*w[1]%MOD*w[1]%MOD;
    	int qu;scanf("%d",&qu);while(qu--) solve();
    	return 0;
    }
    

    61. P5591 小猪佩奇学数学

    还是注意到此题 (n) 很大,而 (k)(2) 的整数次幂,众所周知 (998244353-1=119·2^{23}) 刚好是 (k) 的倍数,因此题目已经疯狂暗示了此题的算法,然后就考虑一阵推式子:

    [egin{aligned} ans&=sumlimits_{i=0}^ndbinom{n}{i}p^i·dfrac{i-imod k}{k}\ &=dfrac{1}{k}sumlimits_{i=0}^ndbinom{n}{i}p^i·i-dfrac{1}{k}sumlimits_{i=0}^ndbinom{n}{i}p^i·imod k\ &=dfrac{1}{k}sumlimits_{i=0}^ndbinom{n-1}{i-1}p^i·n-dfrac{1}{k}sumlimits_{i=0}^ndbinom{n}{i}p^i·sumlimits_{r=0}^{k-1}r[kmid i-r]\ &=dfrac{np}{k}sumlimits_{i=0}^ndbinom{n-1}{i-1}p^{i-1}-dfrac{1}{k^2}sumlimits_{i=0}^ndbinom{n}{i}p^i·sumlimits_{r=0}^{k-1}rsumlimits_{j=0}^{k-1}omega_k^{j(i-r)}\ &=dfrac{np}{k}(p+1)^{n-1}-dfrac{1}{k^2}sumlimits_{i=0}^ndbinom{n}{i}p^i·sumlimits_{r=0}^{k-1}rsumlimits_{j=0}^{k-1}omega_k^{j(i-r)}\ &=dfrac{np}{k}(p+1)^{n-1}-dfrac{1}{k^2}sumlimits_{j=0}^{k-1}(sumlimits_{r=0}^{k-1}r·omega_k^{-jr})·(sumlimits_{i=0}^ndbinom{n}{i}p^iomega_k^{ji})\ &=dfrac{np}{k}(p+1)^{n-1}-dfrac{1}{k^2}sumlimits_{j=0}^{k-1}(sumlimits_{r=0}^{k-1}r·omega_k^{-jr})·(p^iomega_k^{i}+1)^n end{aligned} ]

    式子推到这里,聪明的读者们不难发现我们复杂度瓶颈在于如何计算 (sumlimits_{r=0}^{k-1}r·omega_k^{-jr}),显然这东西可以被抽象为 (sumlimits_{i=0}^{n-1}i·a^i),因此接下来我们考虑如何高效求出这个式子的值(其实《具体数学》上有这方面的推导内容,大概在 P27),我们设 (S=sumlimits_{i=0}^{n}ia^i),那么 (aS=sumlimits_{i=0}^{n}ia^{i+1}=sumlimits_{i=1}^{n+1}(i-1)a^i),两式相减可以得到 ((a-1)S=(n+1)a^{n+1}-sumlimits_{i=1}^{n+1}a^i),然后一个等比数列求和公式带走即可,注意特判 (a=1)

    复杂度 (klog k)

    62. UOJ #450. 【集训队作业2018】复读机

    首先当 (d=1) 时答案显然是 (m^n)

    (k=2) 时每个复读机的 EGF 显然是 (sumlimits_{2mid i}dfrac{x^i}{i!}=cosh x=dfrac{e^x+e^{-x}}{2}),因此答案即为 (n![x^n](dfrac{e^x+e^{-x}}{2})^k),二项式定理一通暴算即可,复杂度 (mathcal O(k))

    (k=3) 时类似地有每个复读机的 EGF 为 (sumlimits_{3mid i}dfrac{x^i}{i!}=sumlimits_{i}dfrac{x^i}{i!}[3mid i]=dfrac{1}{3}sumlimits_{j=0}^2sumlimits_{i}dfrac{x^i·omega_3^{ij}}{i!}),化简一下可以得到 (dfrac{1}{3}(sumlimits_{j=0}^2e^{omega_3^jx})),然后三项式定理(大雾)枚举一下即可,复杂度 (mathcal O(k^2))

    63. HDU 7013 String Mod

    好了,既然你已经学会了这么多,就来试一下昨天的多校 1002 吧(

    首先对于一对 ((i,j)),答案显然可以写成 (sumlimits_{p}sumlimits_{q}dbinom{L}{p,q,L-p-q}·(k-2)^{L-p-q}[pequiv ipmod{n}][qequiv jpmod{n}]),看到 (mod) 以及 (nmid P-1),可以考虑单位根反演,即

    [egin{aligned} ans&=sumlimits_{p}sumlimits_{q}dbinom{L}{p,q,L-p-q}·(k-2)^{L-p-q}[pequiv ipmod{n}][qequiv jpmod{n}]\ &=dfrac{1}{n^2}sumlimits_{p}sumlimits_{q}dbinom{L}{p,q,L-p-q}·(k-2)^{L-p-q}sumlimits_{x=0}^{n-1}sumlimits_{y=0}^{n-1}omega_n^{(p-i)x}omega_n^{(q-j)y}\ &=dfrac{1}{n^2}sumlimits_{x=0}^{n-1}sumlimits_{y=0}^{n-1}dfrac{1}{omega^{ix}}dfrac{1}{omega^{jy}}sumlimits_{p}sumlimits_{q}dbinom{L}{p,q,L-p-q}·(k-2)^{L-p-q}(omega_n^{x})^p(omega_n^{y})^q\ &=dfrac{1}{n^2}sumlimits_{x=0}^{n-1}sumlimits_{y=0}^{n-1}dfrac{1}{omega^{ix}}dfrac{1}{omega^{jy}}(omega_n^x+omega_n^y+k-2)^L end{aligned} ]

    直接算是 (n^2) 的,再加上前面 (i,j) 的复杂度,总复杂度 (n^4),不过发现这个式子中每一项要么与 (i,x) 有关,要么与 (j,y) 有关,要么与 (x,y) 有关,并没有哪一项与 (i,j) 直接相关,因此考虑矩阵乘法,我们记矩阵 (A_{i,j}=dfrac{1}{omega_n^{ij}}),矩阵 (B_{i,j}=(omega_n^i+omega_n^j+k-2)^L),那么答案矩阵即为 (A imes B imes A)(dfrac{1}{n^2})

    总复杂度 (mathcal O(n^3))

    FFT 三次变两次的小技巧

    一个非常 trivial 的小 trick。8 个月前学 FFT 时没学懂现在来补了。

    首先注意到 ( ext{DFT}) 是一个线性变换,因此对于两个序列 (a,b),记 (va)(a) 每一项都乘以 (v) 后的结果,那么有 ( ext{DFT}(a+bsqrt{-1})= ext{DFT}(a)+ ext{DFT}(b)sqrt{-1}),也就是说,假设 (P= ext{DFT}(a),Q= ext{DFT}(b)),那么 ( ext{DFT}(a+bsqrt{-1})=P+sqrt{-1}Q)

    这样还是无法确定出 (P,Q)​​,不过注意到有个东西叫共轭复数,具体来说,对于 (z=a+bsqrt{-1})​​,其共轭复数 (overline{z}=a-bsqrt{-1})​​,因此对于一个序列 (a)​​,我们考虑定义其共轭序列(瞎起名字 ing)(overline{a})​​ 满足 (overline{a}_i=overline{a_i})​​,那么 ( ext{DFT}(overline{a+bsqrt{-1}})= ext{DFT}(a-bsqrt{-1})=P-sqrt{-1}Q)​​,因此如果我们能高效求出 ( ext{DFT}(overline{a+bsqrt{-1}}))​,即 ( ext{DFT}(a-bsqrt{-1}))​,那么对于每一项 (i)​,如果我们设 (X= ext{DFT}(a+bsqrt{-1})_i,Y= ext{DFT}(a-bsqrt{-1})_i)​,有 (P_i+sqrt{-1}Q_i=X,P_i-sqrt{-1}Q_i=Y)​​​,简单二元一次方程组即可求出 (P_i,Q_i)​​。具体来说,假设 (x_1=P_i) 的实部,(y_1=P_i) 的虚部,(x_2,y_2) 也同理,那么:

    [egin{cases} x_1-y_2= ext{Re}(X)\ y_1+x_2= ext{Im}(X)\ x_1+y_2= ext{Re}(Y)\ y_1-x_2= ext{Im}(Y) end{cases} ]

    解得

    [egin{cases} x_1=dfrac{ ext{Re}(X)+ ext{Re}(Y)}{2}\ y_1=dfrac{ ext{Im}(X)+ ext{Im}(Y)}{2}\ x_2=dfrac{ ext{Im}(X)- ext{Im}(Y)}{2}\ y_2=dfrac{ ext{Re}(Y)- ext{Re}(Y)}{2}\ end{cases} ]

    那么怎么求出 ( ext{DFT}(overline{a+bsqrt{-1}}))​ 呢?注意到 DFT 的过程实际上是将每个 (a_i)​ 变为 (f(omega_n^i))​​​​,因此 ( ext{DFT}(overline{a})_i=sumlimits_{j=0}^noverline{a}_j(omega_n^i)^j)​,又有:

    • (overline{ab}=overline{a}·overline{b})
    • (overline{omega_{n}^i}=omega_n^{n-i})

    因此 ( ext{DFT}(overline{a})_i=sumlimits_{j=0}^noverline{a}_joverline{(omega_n^{n-i})^j}=overline{sumlimits_{j=0}^na_j(omega_n^{n-i})^j}),不难发现对于 (i=0) 而言,由于 (omega_{n}^n=1),后面那东西就是 (overline{ ext{DFT}(a)_0}),而对于 (i e 0),后面那东西就是 (overline{ ext{DFT}(a)_{n-i}}),因此我们求出 ( ext{DFT}(a+bsqrt{-1})) 后,把这个序列第 (1) 项至第 (n-1) 项 reverse 一下并把每一项的虚部变为其相反数即可得到 ( ext{DFT}(overline{a+bsqrt{-1}}))​。这样即可一次 DFT+一次 IDFT 实现 FFT(

    const int MAXP=1<<21;
    const double Pi=acos(-1);
    int n,m,LEN=1;
    struct comp{
    	double x,y;
    	comp(double _x=0,double _y=0):x(_x),y(_y){}
    	comp operator +(const comp &rhs){return comp(x+rhs.x,y+rhs.y);}
    	comp operator -(const comp &rhs){return comp(x-rhs.x,y-rhs.y);}
    	comp operator *(const comp &rhs){return comp(x*rhs.x-y*rhs.y,x*rhs.y+y*rhs.x);}
    	comp operator /(const double &rhs){return comp(x/rhs,y/rhs);}
    } a[MAXP+5],b[MAXP+5];
    int rev[MAXP+5];
    void FFT(comp *a,int len,int type){
    	int lg=31-__builtin_clz(len);
    	for(int i=0;i<len;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<lg-1);
    	for(int i=0;i<len;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
    	for(int i=2;i<=len;i<<=1){
    		comp W=comp(cos(2*Pi/i),type*sin(2*Pi/i));
    		for(int j=0;j<len;j+=i){
    			comp w=comp(1,0);
    			for(int k=0;k<(i>>1);k++,w=w*W){
    				comp X=a[j+k],Y=w*a[(i>>1)+j+k];
    				a[j+k]=X+Y;a[(i>>1)+j+k]=X-Y;
    			}
    		}
    	} if(!~type) for(int i=0;i<len;i++) a[i].x=(int)(a[i].x/len+0.5);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<=n;i++) scanf("%lf",&a[i].x);
    	for(int i=0;i<=m;i++) scanf("%lf",&a[i].y);
    	while(LEN<=n+m) LEN<<=1;FFT(a,LEN,1);
    	for(int i=0;i<LEN;i++){
    		comp x=a[i],y=(!i)?a[i]:a[LEN-i];y.y=-y.y;
    		comp A=(x+y)/2.0,B=(x-y)/2.0;swap(B.x,B.y);B.y=-B.y;
    		b[i]=A*B;
    	} FFT(b,LEN,-1);
    	for(int i=0;i<=n+m;i++) printf("%d%c",(int)b[i].x," 
    "[i==n+m]);
    	return 0;
    }
    

    各种多项式的 (n^2) 版本

    qwq 大概是为了为下面子集卷积的高级操作做铺垫(?)

    博客戳这儿

    子集卷积的一些高级操作

    首先在开始正题之前我们先得知道什么是集合幂级数,集合幂级数大概就是一个形如 (f(x)=sumlimits_{Ssubseteq U}a_Sx^S) 的幂级数 (f),其中 (U) 是一个给定的有限集合。与形式幂级数不同的是,(x^S) 上方的指数在这种定义下全部是全集 (U)一个个子集 instead of 一个个非负整数(当然,在 OI 中,由于用二进制表示集合这种方法的存在,我们也可以将 (x) 上方的指数视作一个个在 ([0,2^{|U|})) 中的二进制数,这样全集可视为 (2^{|U|}-1))。与形式幂级数的加法卷积类似,我们也可以定义 or 卷积、and 卷积、xor 卷积等,分别表示两个集合幂级数 (F,G) 相乘,([x^S]F(x) imes[x^T]G(x)) 的系数贡献到 (x^{Scup T},x^{Scap T},x^{Soplus T}) 的情况,对于这些卷积你都可以在我的快速沃尔什变换&快速莫比乌斯变换小记中找到,当然由于这里我们将着重探讨子集卷积,所以对于其他的卷积咱也大可不必花心思赘述了(

    子集卷积,大概也是 ([x^S]F(x) imes[x^T]G(x))​ 的系数贡献到 (x^{Scup T})​ 的情况,不过有一个前提就是 (Scap T=varnothing)​ 时才能产生贡献,否则贡献为 (0)​。那么怎么快速求出两个集合幂级数 (F,G)​ 的子集卷积呢?注意到关于集合的并,有一个性质 (|S|+|T|ge|Scup T|)​,因此我们考虑将集合幂级数写成一个二元函数的形式(形式而已,并不是真正在集合幂级数后面加一维),即将每个 (a_Sx^S)​ 扩展成 (a_Sx^Sy^{|S|})​​ 的形式,这样每个集合幂级数可以写作 (sumlimits_{nge 0}sumlimits_{mge 0}a_{n,m}x^ny^m)​​,对于两个集合幂级数 (F,G),假设它们的系数分别为 (f_{n,m})(g_{n,m}),那么我们重定义它们的乘法为 (F imes G=sumlimits_{nge 0}sumlimits_{mge 0}(sumlimits_{p|q=n}sumlimits_{r+s=m}f_{p,r}g_{q,s})x^ny^m),也就是 (f_{p,r}g_{q,s}) 贡献到 (x^{p|q}y^{r+s}) 的位置,这样我们取它们乘积 (x^Sy^{|S|}) 前的系数作为它们子集卷积 (x^S) 前的系数即可,不难发现这样一来,两个集合 (S,T) 如果满足 (Scap T evarnothing),那么其就一定不满足 (|Scap T|=|S|+|T|),也就一定不会贡献到 (x^{Scup T}y^{|Scup T|}) 处,也就证明了上述做法的正确性。

    那么这东西该怎么实现呢,我们考虑将集合幂级数 (F(x)) 扩充之后的样子写成 (sumlimits_{S}x^SG_S(y))​ 的形式,其中 (G_S(y)) 是一个关于 (y)​​ 的形式幂级数,这样不难发现我们的乘法运算可以视作:将每个集合幂级数前的系数视作一个形式幂级数,系数的乘法视作多项式的乘法,然后对它们做一遍 or 卷积。因此考虑按照套路 FWTor,然后对每个 (x^S),将两个集合幂级数 (x^S) 前的系数进行多项式乘法,然后 IFWTor 回去即可。复杂度 (2^nn^2)

    注意到这里涉及形式幂级数的操作,因此我们也可以按照形式幂级数定义它们的逆、(ln)(exp)。具体来说,对于集合幂级数 (F),我们定义:

    • 逆:定义 (F) 的逆为满足 (F imes G=epsilon) 的集合幂级数 (G),其中 ( imes) 在这部分默认为子集卷积,(epsilon) 为满足 ([x^S]epsilon=[S=varnothing]) 的集合幂级数。
    • (exp):定义 (exp F) 为满足 (G=sumlimits_{nge 0}dfrac{F^n}{n!}) 的集合幂级数 (G)
    • (ln):定义 (ln F) 为满足 (exp G=F) 的集合幂级数 (G)
    • (exp_{le k}):定义 (exp_{le k})​ 为满足 (G=sumlimits_{n=0}^kdfrac{F^n}{n!}) 的集合幂级数

    由于我们子集卷积可以看作是将集合幂级数都一遍 FWTor,然后每一项按照形式幂级数的套路卷起来,再 IFWTor,因此上述操作也可视作,将集合幂级数 FWTor 一遍,然后每一个 (x^S) 前的系数分别 ( ext{inv}/ln/exp/exp_{le k})。注意,由于集合幂级数的题 (n) 一般都很小,因此在这里就大可不必 NTT 实现多项式 ( ext{inv}/ln/exp/exp_{le k}) 了,可以平方地递推,具体递推方法可见上面那篇 blog。

    64. P6570 [NOI Online #3 提高组] 优秀子序列

    题解

    65. P6846 [CEOI2019] Amusement Park

    注意到对于一种翻转边集的状态,如果将所有边的状态反转,那么得到的图仍是一个 DAG,也就是说我们可以将所有翻转某个边集,使得得到的图是一个 DAG 的方案两两配对,并使每对中翻转的边集数量之和恰好等于 (m)。因此我们只用算出有多少种翻转边集之后是 DAG 的方案然后乘上 (dfrac{m}{2}) 即可。

    考虑怎么算翻转之后是 DAG 的方案,我们考虑设 (f_S) 表示集合 (S)​ 中形成 DAG 的方案数,那么考虑钦定一些点入度为 (0),记这个集合为 (T),那么显然 (T) 必须是一个独立集,否则总会存在 (T)​ 中的点入度非零,考虑枚举这个集合 (T),那么显然 (S-T) 也应是一个 DAG,但这样会算重,因此考虑容斥,即

    [f_S=sumlimits_{varnothing e Tsubseteq S}[T ext{ is an independent set}]·(-1)^{|T|+1}f_{S-T} ]

    由于 Latex 上用中文太鸡肋了就换用了英文

    注意到这东西可以写成子集卷积的形式,具体来说,即 (F)(f) 的“生成集合幂级数”,(G(x)) 为满足 ([x^T]G(x)=[T ext{ is an independent set}]·(-1)^{|T|+1}),那么 (FG=F-1),即 (F=dfrac{1}{1-G}),子集 inv 一波即可。

    66. LOJ #154 集合划分计数

    搞不懂模板题卡常是啥心态

    (F)​ 为满足 ([x^S]F(x)=[xinmathcal F]),那么我们对 (F)(exp_{le k}) 即可。

    只不过此题过于卡常,所以交了 114514191981019260817998244353 发

    卡常技巧:

    1. ( ext{exp}_k) 时候,如果该多项式最低非零项次数 (>dfrac{n}{k}) 就不用快速幂了,直接将快速幂得到的数组每一项设为 (0) 即可。
    2. 在暴力多项式乘法时,可以找到两个多项式最低和最高的非零项 (la,ra)(lb,rb),然后只枚举次数在 ([la,ra])([lb,rb]) 的范围内的数即可,这样效率可以高不少。

    不过还是几乎喜提最劣解

    人傻常数大,需要狠命卡

    67. LOJ #6673 EntropyIncreaser 与山林

    首先先不考虑连通这个条件,考虑怎样求有多少张子图 (G’=(V’,E’)),满足 (V’=S),且 (G’) 中每个连通块都有欧拉回路,记这个方案数为 (f_S)。显然,对于一张图而言,每个连通块都有欧拉回路的充要条件是每个点的度都是偶数,因此我们考虑对每条边新建一个布尔型变量表示其有没有选,这样我们可以列出 (|S|) 个方程组,高斯消元一下,那么 (f_S) 就是 (2) 的自由元个数次方。

    接下来考虑带上连通这个条件后怎么处理,我们记 (F(x)) 为满足 ([x^S]F(x)=f_S) 的集合幂级数,再设 (G(x)) 表示 ([x^S]G(x)=)(S) 为点集的、存在欧拉回路(不是每个连通块都有欧拉回路)的子图个数,那么根据 P4841 的套路有 (exp G=F)。现在已知 (F),子集 (ln) 一波即可求出 (G)

    68. UOJ #94 【集训队互测2015】胡策的统计

    考虑记 (f_S)​ 为以 (S)​ 为点集的子图个数,那么显然有 (f_S=2^{cnt_S})​,其中 (cnt_S)​ 为 (S)​ 内部边的数量,再设 (g_S)​ 为以 (S)​ 为点集的连通子图个数,那么设 (F,G)​ 分别为 (f,g)​ 对应的集合幂级数,显然就有 (F=exp G)​,(ln)​ 一下可求出 (G)​。再设 (h_S)​ 为以集合 (S)​ 为点集的所有子图的连通值之和,也对应地设其生成集合幂级数为 (H)​,那么 (H=sumlimits_{nge 0}G^n),也就是 (exp) 里面去掉分母上的 (n!),也就相当于对每个 (n) 个连通块的方案乘了个 (n!),注意到这东西显然等于 (dfrac{1}{1-G}),因此再一波子集 (ln) 求出 (H),最终答案就是 (H_U)

    69. NFLSOJ #1060. 【2021 六校联合训练 NOI #40】白玉楼今天的饭

    题解

  • 相关阅读:
    struts2类型转换
    struts2拦截器
    计算机系统结构
    struts2标签
    struts2 OGNL表达式
    使用bootstrap
    Struts2-综合项目
    拦截器,课3
    struts2之OGNL
    Struts2框架
  • 原文地址:https://www.cnblogs.com/ET2006/p/fftnttdxsschs3.html
Copyright © 2020-2023  润新知