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 \ ...
随机推荐
- android仿win8
在 eoe上偶然发现已经有人实现了这个功能的源码(地址:http://www.eoeandroid.com /forum.php?mod=viewthread&tid=327557),马上下载 ...
- Android开发随笔5
昨天: 对界面的进一步设计补充 可以在界面之间的跳转 研究了对图标等的操作 今天: 实现对库的相关操作 学习视视频内容‘ 复习java的一些知识.
- Calculation PartⅡ
GitHub/object-oriented 误删内容--周末修复
- 【Docker 命令】- ps命令
docker ps : 列出容器 语法 docker ps [OPTIONS] OPTIONS说明: -a:显示所有的容器,包括未运行的. -f:根据条件过滤显示的内容. --format :指定返回 ...
- 第一部分shell编程1基础知识
ls etc/init.d/ shell脚本的路径 ls /usr/local/apache2/ ls /usr/local/apache2/bin/apachectl 1. shell特性命令历史 ...
- centos升级python(从2.6.6升级到2.7.8)
***先安装readline,否则升级后python回退和方向键不能使用 yum install readline-devel.x86_64 1.#wget www.python.org/ftp/ ...
- %pylab ipython 中文
格式:%pylab [--no-import-all] [gui] 该命令会在ipython或notebook环境中自动加载numpy和matplotlib库,跟以下语句功能一致 import num ...
- [剑指Offer] 64.滑动窗口的最大值
题目描述 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值.例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6 ...
- matlab padarray
功能:填充图像或填充数组 使用:B = padarray(A,padsize,padval,direction) A表示输入图像,B是填充后的图像,padsize给出了填充的行数和列数,通常用[r c ...
- BZOJ 1057 棋盘制作(最大01相间子矩阵)
求最大01相间子矩阵可以转换为求最大全0子矩阵.只需把棋盘(x+y)为奇数的取反,而该问题可以用经典的悬线法O(n^2)的求解. 悬线法呢. 首先定义b[i][j],为a[i][j]向上的最大连续0的 ...