51nod 1806 wangyurzee的树
可是wangyurzee发现方案数太多了,于是他又给出了m个限制条件,其中第i个限制条件限制了编号为u[i]的节点的度数不能为d[i]。
一个节点的度数,就是指和该节点相关联的边的条数。
这样一来,方案数就减少了,问题也就变得容易了,现在请你告诉wangyurzee连边的方案总数为多少。
答案请对1000000007取模。
总方案共有3种,分别为{(1,2),(1,3)},{(1,2),(2,3)},{(2,3),(1,3)}。其中第二种方案节点1的度数为2,不符合要求,因此答案为2。
第一行输入2个整数n(1<=n<=1000000),m(0<=m<=17)分别表示节点个数以及限制个数。
第2行到第m+1行描述m个限制条件,第i+1行为2个整数u[i],d[i],表示编号为u[i]的节点度数不能为d[i]。
为了方便起见,保证1<=ui<=m。同时保证1<=ui<=n,1<=di<=n-1,保证不会有两条完全相同的限制。
输出一行一个整数表示答案。
3 1
1 2
2
树 prufer编码 数学问题 容斥
算度数不为d[i]的方案数看上去不可做,考虑算度数为d[i]的方案数。
首先我们知道n个点有标号生成树的数量为 $ n^{n-2} $
注意到限制条件m很小,可以计算不满足一个条件的方案数,不满足两个条件的方案数,不满足三个条件的方案数……然后容斥一下。
假设当前计算不满足某x个条件的方案数:
若一个点的度数为 $ d[i] $,那么它在prufer序列中出现了 $ d[i]-1 $次。
现在有x个点的贡献确定了,其度数总和为
$ \sum_{i=1}^{x} d[i] $
那么在prufer序列中有
$ sum=\sum_{i=1}^{x} (d[i]-1) $ 个位置被占用。
占用这么多位置的方案数是
$ C(n-2, sum)$
这些位置里选$d[1]-1$个位置填第1种编号,方案数为
$ C(sum,d[1]-1)$
再选位置填第2种编号,方案数为
$ C(sum-d[1]-1,d[2]-1)$
以此类推
根据乘法原理把上面这些组合数乘起来,化简得到:
$ \frac{(n-2)!}{(n-2-sum)! * \Pi (d[i]-1)!}$
prufer序列中剩下的位置可以任意填不被限制度数的点,共有
$(n-x)^{n-2-sum}$ 种方案
所以符合当前度数限制的方案数有
$ \frac{(n-2)!}{(n-2-sum)! * \Pi (d[i]-1)!} * (n-x)^{n-2-sum}$
注意:可能出现两个限制条件同时限制一个点的度数,需要特判
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
using namespace std;
const int mod=1e9+;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int inv[mxn],fac[mxn];
void init(int n){
n+=;
inv[]=inv[]=;fac[]=fac[]=;
for(int i=;i<=n;i++){
fac[i]=(LL)fac[i-]*i%mod;
inv[i]=((-mod/i*(LL)inv[mod%i])%mod+mod)%mod;
}
for(int i=;i<=n;i++)inv[i]=(LL)inv[i-]*inv[i]%mod;
return;
}
int n,m;
int u[],d[];bool vis[];
LL ans=;
int ksm(int a,int k){
int res=;
while(k){
if(k&)res=(LL)res*a%mod;
a=(LL)a*a%mod;
k>>=;
}
return res;
}
int main(){
int i,j;
n=read();m=read();
if(n==){printf("1\n");return ;}
init(n);
for(i=;i<m;i++){
u[i]=read();d[i]=read();
}
ans=ksm(n,n-);
int ed=<<m;
for(int S=;S<ed;S++){//枚举状态
int tmp=S,smm=,cnt=;bool flag=;
LL down=;
memset(vis,,sizeof vis);
for(i=;i<m;i++){
if((S>>i)&){
if(vis[u[i]]){flag=;break;}//限制重复
vis[u[i]]=;
smm+=d[i]-;
++cnt;
down=down*inv[d[i]-]%mod;
}
}
if(!flag)continue;
if(smm>n-)continue;
LL up=fac[n-];
up=up*down%mod*inv[n--smm]%mod;
up=up*ksm(n-cnt,n--smm)%mod;
(ans+=(cnt&)?-up:up)%=mod;
}
ans=(ans+mod)%mod;
printf("%lld\n",ans);
return ;
}
51nod 1806 wangyurzee的树的更多相关文章
- 【题解】51nod 1806 wangyurzee的树
看这道题目懵逼了好久, \(m <= 17\) 一眼容斥,然而并没有想到怎么求出生成树的个数.然后灵光一闪——我不是学过一个叫Prüfer编码的东西嘛?!那就完美解决啦~ Prüfer编码就是将 ...
- 51nod 1443 路径和树(最短路)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1443 1443 路径和树 题目来源: CodeForces ...
- 51nod 1681 公共祖先 | 树状数组
51nod 1681 公共祖先 有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完 ...
- 51Nod 1737 配对(树的重心)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737 题意: 思路: 树的重心. 树的重心就是其所以子树的最大的子树结点 ...
- 51nod 1272 思维/线段树
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1272 1272 最大距离 题目来源: Codility 基准时间限制:1 ...
- 51Nod 1443 路径和树 —— dijkstra
题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1443 首先要得到一个最短路树: 注意边权和最小,因为在最短路中,每 ...
- 51nod 1443 路径和树(最短路树)
题目链接:路径和树 题意:给定无向带权连通图,求从u开始边权和最小的最短路树,输出最小边权和. 题解:构造出最短路树,把存留下来的边权全部加起来.(跑dijkstra的时候松弛加上$ < $变成 ...
- 51Nod 1443 路径和树
还是一道很简单的基础题,就是一个最短路径树的类型题目 我们首先可以发现这棵树必定满足从1出发到其它点的距离都是原图中的最短路 换句话说,这棵树上的每一条边都是原图从1出发到其它点的最短路上的边 那么直 ...
- 51Nod 1680 区间求和 树状数组
题意: 给出一个长度为\(n\)的数列\(A_i\),定义\(f(k)\)为所有长度大于等于\(k\)的子区间中前\(k\)大数之和的和. 求\(\sum_{k=1}^{n}f(k) \; mod \ ...
随机推荐
- [基于NetCore的简单博客系统]-登录
0-项目背景 一个基于.NET CORE RAZOR PAGES的简单博客系统 技术栈全部采用微软官方实现方式,目的是熟悉新技术 项目地址:https://github.com/ganqiyin/BL ...
- OSPF学习中的问题
OSPF对接两方,对设置的要求,哪些参数必须相同 (HELLO &dead interval, area ID, authentation, 末节区域(option中的E位), network ...
- epoll&ext4文件系统
1.第一个终端运行nesttest,nesttest首先fork一个子进程,然后父进程退出,子进程首先打开一个txt普通文件对应fd为3,然后创建一个epfd,对应fd为4 lybxin@Inspir ...
- 【Python】Python中的引用和赋值
本文转自:http://my.oschina.net/leejun2005/blog/145911 在 python 中赋值语句总是建立对象的引用值,而不是复制对象.因此,python 变量更像是指针 ...
- RT-thread 设备驱动组件之IIC总线设备
本文主要介绍RT-thread中IIC总线设备驱动,涉及到的主要文件有:驱动框架文件(i2c_core.c,i2c_dev.c,i2c-bit-ops.c,i2c_dev.h,i2c.h):底层硬件驱 ...
- Java基础之开关语句详解
switch 语句是单条件多分支的开关语句,它的一般格式定义如下(其中break语句是可选的): switch(表达式) { case 常量值: 若干个语句 break; case 常量值: 若干个 ...
- [NOI2009]管道取珠 DP + 递推
---题面--- 思路: 主要难点在思路的转化, 不能看见要求$\sum{a[i]^2}$就想着求a[i], 我们可以对其进行某种意义上的拆分,即a[i]实际上可以代表什么? 假设我们现在有两种取出某 ...
- Android 自定义View消除锯齿实现图片旋转,添加边框及文字说明
先看看图片的效果,左边是原图,右边是旋转之后的图: 之所以把这个写出来是因为在一个项目中需要用到这样的效果,我试过用FrameLayout布局如上的画面,然后旋转FrameLayout,随之而来也 ...
- BZOJ1857:[SCOI2010]传送带——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1857 Description 在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段.两条传送 ...
- HDU.2503 a/b + c/d (分式化简)
a/b + c/d Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...