原文链接https://www.cnblogs.com/zhouzhendong/p/CF1109D.html

题意

所有边权都是 [1,m] 中的整数的所有 n 个点的树中,点 a 到点 b 的距离恰好是 m 的有几个。

$$n,m\leq 10^6$$

题解

首先显然 a 和 b 的具体值是没用的。

于是我们就可以直接计数:

枚举树链 ab 上除了 a 和 b 有几个节点,假设是 i 个节点,那么这种情况下的方案总数是多少?

首先,ab 路径上 i+1 条 [1,m] 的边的和是 m ,共有 $\binom{m-1}{i}$ 种边权的取值;

然后,ab 路径上共有 i 个点,方案数是从剩下的 n-2 个点种选出 i 个并排列,即 $\binom{n-2}i i!$ 。

然后,剩下的 n-2-i 条边每条都有 m 种取值,方案数是 $m^{n-2-i}$ 。

最后,考虑生成树的个数,用 prufer 序列的结论推一推就可以知道方案数是 $n^{n-3-i}(i+2)$ 。

所以答案是

$$\sum_{i=0}^{n-2} \binom{n-2}{i}\binom{m-1}{i}m^{n-2-i}n^{n-3-i}i!(i+2)$$

UPD(2019-03-04): 更新一下关于那个 prufer 编码推出的公式的证明:

prufer 编码有几个性质:

1. 假如是 n 个点,那么编码长度为 n-2 ,且每一个位置可以放 1~n 之间的任意数,每一个 prufer 编码与每一个树一一对应。

2. 假设树中一个点 x 的度是 d[x] ,那么在对应的 prufer 编码中,x 出现 d[x]-1 次。

假设我们有 n 个点,被分成了 k 个点集,每个点集里的点已经连通,不同点集之间的点两两无边,现在我们要在这个 n 个点 n-k 条边的基础上求生成树个数。设第 i 个点集包含的点数为 size[i] 。

那么,如果我们把这 k 个点集每一个点都看作一个点,做一个 k 个点的生成树,那么有 $k^{k-2}$ 种方案;但是由于这里的每一个点都是一个点集,所以假设它是点集 i,那么从他连出去的每一条边的属于集合i的端点,都有 size[i] 种选法。也就是说,对于一个 k 个点的 prufer 编码,假设在这个编码中,数字 i 出现了 c[i] 次,那么这个编码对应到原树上就会贡献 $\prod_{i=1}^k size[i] ^ {c[i]+1} $ 次。

我们把每一个 "c[i]+1" 中多出来的 1 提出,看作常量,我们来对于所有 prufer 编码求贡献总和:

$$\sum_{P是一个prufer编码}\ \ \ \ \ \prod_{i=1}^k size[i] ^ {c[i]}$$ 。

考虑到这个prufer编码的每一位选择第 i 个点集,就会对乘积有 $size[i]$ 的贡献,根据乘法分配律,我们可以得到上面的那个式子就是: $(\sum_{i=1}^k size[i])^{k-2} = n ^ {k-2}$ 。

再乘上之前提出的东西,所以答案就是:

$$(\sum_{i=1}^k size[i])^{k-2} \cdot \prod_{i=1}^k size[i] $$

本题要求的那个,只是这个模型的弱化版。至此已经可以解决这个问题了。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=1000005,mod=1e9+7;
int n,m,a,b;
int Fac[N],Inv[N];
int C(int n,int m){
if (m>n||m<0)
return 0;
return (LL)Fac[n]*Inv[m]%mod*Inv[n-m]%mod;
}
int Pow(int x,int y){
if (y<0)
return Pow(x,y+mod-1);
int ans=1;
for (;y;y>>=1,x=(LL)x*x%mod)
if (y&1)
ans=(LL)ans*x%mod;
return ans;
}
void init(int n){
for (int i=Fac[0]=1;i<=n;i++)
Fac[i]=(LL)Fac[i-1]*i%mod;
Inv[n]=Pow(Fac[n],mod-2);
for (int i=n;i>=1;i--)
Inv[i-1]=(LL)Inv[i]*i%mod;
}
void Add(int &x,int y){
if ((x+=y)>=mod)
x-=mod;
}
int main(){
n=read(),m=read(),a=read(),b=read();
init(max(n,m));
int ans=0;
for (int i=0;i<=n-2;i++)
Add(ans,(LL)C(n-2,i)*C(m-1,i)%mod*Fac[i]%mod
*Pow(m,n-2-i)%mod*Pow(n,n-3-i)%mod*(i+2)%mod);
cout<<ans<<endl;
return 0;
}

  

Codeforces 1109D. Sasha and Interesting Fact from Graph Theory 排列组合,Prufer编码的更多相关文章

  1. Codeforces 1109D. Sasha and Interesting Fact from Graph Theory

    Codeforces 1109D. Sasha and Interesting Fact from Graph Theory 解题思路: 这题我根本不会做,是周指导带飞我. 首先对于当前已经有 \(m ...

  2. Codeforces 1109D Sasha and Interesting Fact from Graph Theory (看题解) 组合数学

    Sasha and Interesting Fact from Graph Theory n 个 点形成 m 个有标号森林的方案数为 F(n, m) = m * n ^ {n - 1 - m} 然后就 ...

  3. CF1109D Sasha and Interesting Fact from Graph Theory

    CF1109D Sasha and Interesting Fact from Graph Theory 这个 \(D\) 题比赛切掉的人基本上是 \(C\) 题的 \(5,6\) 倍...果然数学计 ...

  4. Sasha and Interesting Fact from Graph Theory CodeForces - 1109D (图论,计数,Caylay定理)

    大意: 求a->b最短路长度为m的n节点树的个数, 边权全部不超过m 枚举$a$与$b$之间的边数, 再由拓展$Caylay$定理分配其余结点 拓展$Caylay$定理 $n$个有标号节点生成k ...

  5. Codeforces1113F. Sasha and Interesting Fact from Graph Theory(组合数学 计数 广义Cayley定理)

    题目链接:传送门 思路: 计数.树的结构和边权的计数可以分开讨论. ①假设从a到b的路径上有e条边,那么路径上就有e-1个点.构造这条路径上的点有$A_{n-2}^{e-1}$种方案: ②这条路径的权 ...

  6. CF1109DSasha and Interesting Fact from Graph Theory(数数)

    题面 传送门 前置芝士 Prufer codes与Generalized Cayley's Formula 题解 不行了脑子已经咕咕了连这么简单的数数题都不会了-- 首先这两个特殊点到底是啥并没有影响 ...

  7. Codeforces Round #485 (Div. 2) F. AND Graph

    Codeforces Round #485 (Div. 2) F. AND Graph 题目连接: http://codeforces.com/contest/987/problem/F Descri ...

  8. Codeforces 703D Mishka and Interesting sum 离线+树状数组

    链接 Codeforces 703D Mishka and Interesting sum 题意 求区间内数字出现次数为偶数的数的异或和 思路 区间内直接异或的话得到的是出现次数为奇数的异或和,要得到 ...

  9. CodeForces 840B - Leha and another game about graph | Codeforces Round #429(Div 1)

    思路来自这里,重点大概是想到建树和无解情况,然后就变成树形DP了- - /* CodeForces 840B - Leha and another game about graph [ 增量构造,树上 ...

随机推荐

  1. shutil模块和几种文件上传Demo

    一.shutil模块 1.介绍 shutil模块是对os中文件操作的补充.--移动 复制 打包 压缩 解压 2.基本使用 1. shutil.copyfileobj(文件1, 文件2, 长度) 将文件 ...

  2. 【XSY3139】预言家 数位DP NFA

    题目描述 有一个定义在 \(\{0,1,2,3,4,5,6,7,8,9\}\) 上的合规表达式,包含三种基本的操作: 结合:\(E_1E_2\) 分配:\((E_1|E_2|\ldots|E_n),n ...

  3. 4.1 socket

    socket  背景概念 脑图结构 OSI 模型 socket 概念特性 脑图结构 理解示意图  额外补充 Socket是应用层与 TCP/IP协议族通信的中间软件抽象层,它是一组接口. 在设计模式中 ...

  4. 越光后端开发——ygapi(3.引入xadmin)

    1.引入xadmin 1.将xadmin文件夹放入extra_apps目录下: 2.在每个app下新建adminx.py 1.apps/users/目录下新建adminx.py: import xad ...

  5. 金融量化分析【day112】:量化平台的使用-初始化函数

    一.set_benchmark - 设置基准 1.实现代码 # 导入函数库 import jqdata #初始化函数,设定基准等等 def initialize(context): set_bench ...

  6. Ubuntu设置和查看环境变量

    设置环境变量的三种方法 1.1 临时设置 export PATH=/home/yan/share/usr/local/arm/3.4.1/bin:$PATH 1.2 当前用户的全局设置 打开~/.ba ...

  7. Chrome 禁止从页面打开 Data URI 网址了

    现如今,网民的网络账户被盗,很有可能是被“钓鱼”了.去年的一份安全报告中指出:“近85%的资金损失是通过钓鱼网址泄露支付信息造成的”. 传统的钓鱼网站通常是申请一个和被冒充网站相似的域名,比如 tao ...

  8. NightWatch端到端测试

    NightWatch http://nightwatchjs.org/ Nightwatch.js Browser automated testing done easy. Write End-to- ...

  9. H5——弹性盒

    [flex 弹性盒布局] * 1.给父容器添加display:flex/inline-flex;属性 * 2.父容器可以使用的属性值有: * ① flex-direction 属性决定主轴的方向(即项 ...

  10. Mysql中设置指定IP的特定用户及特定权限

    创建用户:格式:grant select on 数据库.* to 用户名@登录主机 identified by '密码' 举例: 例 1:增加一个用户 test1 密码为 abc,让他可以在任何主机上 ...