• 无向连通图计数的一些想法


    前两天遇到了一个题,机房老哥打算把它出成对答案的计数,中间有一步需要求恰有奇数条边的连通图个数。然后就有人提出推广到对每个 (0leq i<k)(mod kequiv i) 的个数,大致编出来一个 (mathcal O(nklog n)) 的做法。


    Problem. 给出正整数 (n,k),请对每个 (0leq i<2^k) 求出有多少个 (n) 个点的带标号无向连通图满足边数 (mod 2^kequiv i)

    (n2^kleq 10^6),答案对 (998244353) 取模。

    sol.

    考虑记 (f_{i,j})(i) 个点 (j) 条边的无向图个数,(g_{i,j})(i) 个点 (j) 条边的无向连通图个数。考虑其生成函数,(F) 其实是 (G)(x) 一维上做 EGF 卷积,(y) 一维上做 OGF 卷积的结果。记 ( ilde F=sum_{i,j}f_{i,j}frac{x^iy^j}{i!}, ilde G=sum_{i,j}g_{i,j}frac{x^iy^j}{i!}),那么实际上有 ( ilde F=exp ilde G)

    那么我们现在要求的就是 ([x^n]ln ilde Fmod (y^{2^k}-1))。注意到那个模实际上是循环卷积,于是等价于对 (y) 一维做长为 (2^k) 的 FFT,然后求 (ln),最后再 FFT 回来。直接暴力模拟这个过程即可做到 (mathcal O(n2^klog n))

    (k) 足够大的时候,这其实给出了一个优于传统斯特林容斥的 (mathcal O(n^3log n)) 的做法,必可活用于下一次

    #include "poly.h"
    
    int n, k;
    int main() {
    	n = getll(), k = getll();
    
    	std::vector<poly> F(1 << k);
    	for(int i = 0; i < (1 << k); ++i) F[i].redeg(n);
    	
    	ll w = fsp(gen, mod - 1 >> k);
    	for(int i = 0; i <= n; ++i) {
    		poly G; G.redeg((1 << k) - 1);
    		
    		ll cur = 1;
    		for(int j = 0; j < (1 << k); ++j)
    			G[j] = fsp(1 + cur, 1ll * i * (i - 1) / 2), cur = cur * w % mod;
    		
    		for(int j = 0; j < (1 << k); ++j) F[j][i] = G[j];
    	}
    	
    	poly ans; ans.redeg((1 << k) - 1);
    	for(int i = 0; i < (1 << k); ++i) {
    		for(int j = 0; j <= n; ++j) F[i][j] = F[i][j] * Math::Inv(j) % mod;
    		ans[i] = F[i].ln()[n] * Math::Fac(n) % mod;
    	}
    	Poly::NTT(ans, k, -1), ans.print((1 << k) - 1);
    }
    
  • 相关阅读:
    vuex中store分文件时候index.js进行文件整合
    vuex使用 实现点击按钮进行加减
    页面跳转时候拼接在url后面的多个 参数获取
    vue知识点2018.6.3
    vue项目中,main.js,App.vue,index.html如何调用
    locatin
    Json
    Python3基础 list 访问列表中的列表的元素
    Python3基础 list 索引查看元素
    Python3基础 list 查看filter()返回的对象
  • 原文地址:https://www.cnblogs.com/whx1003/p/15331253.html
Copyright © 2020-2023  润新知