zoukankan      html  css  js  c++  java
  • Codeforces 1109D sasha and interesting fact from graph theory

    题目链接:Codeforces1109D

    题意

    求满足以下条件的带标号树的个数:

    • 边权在([1,m]cap Z)

    • (a)到点(b)间的边权和为(m)

    数据范围:(n,m≤1e6)

    题解

    枚举(a),(b)间点数为(i),可以知道方案数为:

    [dbinom{n - 2}{i}dbinom{m-1}{i}i!m^{n-2-i} f(i) ]

    (dbinom{n-2}{i}i!) 是在剩下(n-2)个点中选(i)个排在(a),(b)之间。

    (dbinom{m-1}{i})(i+1)条边和为(m)的方案数。

    (m^{n-2-i}) 是不在(a),(b)之间的点可以自由选择权值。

    (f(i)) 是有一个长为(i+2)的链(以(a),(b)为端点)和(n-i-2)个独立的点的生成树个数。

    事实上,要计算(f(i)),我们可以用一个更强的结论:

    已知有(n)个点和(k)个联通的点集,第(i)个点集大小为(size[i]),那么它生成树的个数为:

    [(Pi_{i=1} ^ {k} size[i])n^{k-2} ]

    (P)是长度为(k-2)(prufer)序列的集合,(P)中的每个元素和一个(k)个点的生成树一一对应。

    但和一般的(k)个点生成树不同。这里第(i)个点的度数(+1),会使答案乘上(size[i])

    设第(i)个点集出现在(prufer)序列中的次数为(c_i),那么我们要求的答案就是:

    [sum_{pin P} Pi_{i=1}^{k} size[i]^{c_i+1} ]

    把那个(+1)提到外面去,就是考虑计算

    [sum_{pin P} Pi_{i=1}^{k} size[i]^{c_i} ]

    因为(sum c_i = k-2) , 这就相当于走(k-2)步,如果走第(i)条就产生(size[i])的贡献,求所有方案下的贡献和。

    这个就是((sum size[i]) ^ {k-2} = n ^ {k - 2})

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    
    int n, m, a, b;
    int fac[N], fav[N], inv[N];
    
    int Qpow(int x, int p) {
    	if (p == -1) return inv[x];
    	int ans = 1;
    	while (p) {
    		if (p & 1) ans = 1LL * ans * x % mod;
    		x = 1LL * x * x % mod;
    		p >>= 1;
    	}
    	return ans;
    }
    
    int C(int x, int y) {
    	if (x < y || y < 0) return 0;
    	return 1LL * fac[x] * fav[y] % mod * fav[x - y] % mod;
    }
    
    void upd(int &x, int y) {
    	(x += y) >= mod ? x -= mod : 0;
    }
    
    int main() {
    	cin >> n >> m >> a >> b;
    	int ans = 0;
    	fac[0] = fav[0] = 1;
    	for (int i = 1; i < N; ++i) {
    		inv[i] = Qpow(i, mod - 2);
    		fac[i] = 1LL * fac[i - 1] * i % mod;
    		fav[i] = 1LL * fav[i - 1] * inv[i] % mod;
    	}
    	for (int i = 0; i <= n - 2; ++i) {
    		int tmp = 1LL * C(n - 2, i) * C(m - 1, i) % mod;
    		tmp = 1LL * tmp * fac[i] % mod;
    		tmp = 1LL * tmp * Qpow(m, n - 2 - i) % mod;
    		tmp = 1LL * tmp * (i + 2) % mod;
    		tmp = 1LL * tmp * Qpow(n, n - i - 3) % mod;
    		upd(ans, tmp);
    	}
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    C# 委托的妙文相当适合我
    分享18个常用的网站性能测试工具
    使用Intelligencia.UrlRewriter重写有后缀及无后缀的url
    c#socket发送邮件详解
    欧美经典怀旧超级经典老歌!STARSHIP
    软件工程之百科名片SQA
    昨天订了道奇酷威
    陈淑桦梦醒时分
    TT已售
    组织过程资产与事业环境因素
  • 原文地址:https://www.cnblogs.com/Vexoben/p/11728699.html
Copyright © 2011-2022 走看看