看这道题目懵逼了好久, \(m <= 17\) 一眼容斥,然而并没有想到怎么求出生成树的个数。然后灵光一闪——我不是学过一个叫Prüfer编码的东西嘛?!那就完美解决啦~

  Prüfer编码就是将一棵无根树映射到一串编码上的编码方法,一棵 \(n\) 个节点的树与一个长度为 \(n - 2\) 的编码串一一对应。所以我们要求合法的 = 总数 \(n ^ {n - 2}\) - 不合法的方案数。不合法的方案数 = 至少有 \(1\) 个不合法 - 至少有 \(2\) 个不合法 + 至少有\(3\) 个不合法……有何求出至少有 \(k\) 个不合法的方案数呢?

  我们可以首先搜索出这 \(k\) 个限制(复杂度约为 \(2^{17}\)),然后令这\(k\) 个限制的 \(sum = \sum d[i] - 1\),\(sum\) 即为这 \(k\) 个限制中所牵涉到的节点在数列中一共应该出现的次数。满足这个限制(每一个节点出现 \(d[i] - 1\) 次)的数列个数即为 \(\frac{sum!}{\prod (d[i] - 1)!}\)。又因为这 \(sum\) 个数可以出现在长度为 \(n - 2\) 的数列中的任何位置,所以 乘上\(C(n - 2, sum)\),剩下的 \(n - 2 - sum\) 个数则可以随便选择,有 \((n - k) ^ {n - sum - 2}\) 种方案。完美~

#include <bits/stdc++.h>
using namespace std;
#define maxn 2000000
#define int long long
#define mod 1000000007
int n, m, fac[maxn];
int cnt, tot = , Ans = , S[maxn];
bool mark[maxn], vis[maxn]; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} struct node
{
int x, d;
}Q[maxn]; int Qpow(int x, int timer)
{
int base = ;
for(; timer; timer >>= , x = x * x % mod)
if(timer & ) base = base * x % mod;
return base;
} int C(int n, int m)
{
if(m > n) return ;
return fac[n] * Qpow(fac[m], mod - ) % mod * Qpow(fac[n - m], mod - ) % mod;
} void Search(int now, int last)
{
if(m - last + < now) return;
if(!now)
{
int tem = , sum = ;
for(int i = ; i <= cnt; i ++)
tem = tem * (fac[Q[S[i]].d - ]) % mod,
sum += Q[S[i]].d - ;
if(sum > n - ) return;
tem = Qpow(tem, mod - );
tem = tem * fac[sum] % mod * C(n - , sum) % mod * Qpow(n - cnt, n - sum - ) % mod;
if(cnt & ) Ans = (Ans - tem + mod) % mod;
else Ans = (Ans + tem) % mod;
return;
}
for(int i = last; i <= m; i ++)
{
if(vis[Q[i].x]) continue;
S[++ cnt] = i, vis[Q[i].x] = ; Search(now - , i + );
cnt --, vis[Q[i].x] = ;
}
} signed main()
{
n = read(), m = read();
for(int i = ; i <= m; i ++)
Q[i].x = read(), Q[i].d = read();
if(n - > ) Ans = Qpow(n, n - );
else
{
printf("1\n");
return ;
}
fac[] = ;
for(int i = ; i <= n; i ++) fac[i] = fac[i - ] * i % mod;
for(int i = ; i <= m; i ++) Search(i, );
printf("%lld\n", Ans);
return ;
}

【题解】51nod 1806 wangyurzee的树的更多相关文章

  1. 51nod 1806 wangyurzee的树

    基准时间限制:1 秒 空间限制:131072 KB    wangyurzee有n个各不相同的节点,编号从1到n.wangyurzee想在它们之间连n-1条边,从而使它们成为一棵树.可是wangyur ...

  2. 题解 P1276 校门外的树(增强版)

    前言 本蒟蒻重学线段树,发现了这道题可以用线段树做. 虽然数据范围很小可以直接暴力,但由于在练习线段树所以打算用线段树写这道题. 本题解针对已经有线段树基础的巨佬,不懂线段树原理的话可以学习线段树后再 ...

  3. 51nod 1443 路径和树(最短路)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1443 1443 路径和树 题目来源: CodeForces ...

  4. 51nod 1443 路径和树(最短路树)

    题目链接:路径和树 题意:给定无向带权连通图,求从u开始边权和最小的最短路树,输出最小边权和. 题解:构造出最短路树,把存留下来的边权全部加起来.(跑dijkstra的时候松弛加上$ < $变成 ...

  5. 51nod 1681 公共祖先 | 树状数组

    51nod 1681 公共祖先 有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完 ...

  6. 51Nod 1737 配对(树的重心)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737 题意: 思路: 树的重心. 树的重心就是其所以子树的最大的子树结点 ...

  7. 51nod 1272 思维/线段树

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1272 1272 最大距离 题目来源: Codility 基准时间限制:1 ...

  8. HH的项链题解(离线思想+链表+树状数组)

    本人第一篇博客重磅推出!!! 希望各位朋友以后多多捧场也多给写意见(我个人喜欢把题解写得啰嗦一点,因为这样方便理解,各位巨佬勿喷) 来讲一道提高+/省选-的骚题:HH的项链(这个HH你理解成皇后呵呵哈 ...

  9. 51nod 1376【线段树维护区间最大值】

    引自:wonter巨巨的博客 定义 dp[i] := 以数字 i(不是下标 i)为结尾的最长上升长度 然后用线段树维护 dp[i]: 每个节点维护 2 个信息,一个是当前区间的最大上升长度,一个是最大 ...

随机推荐

  1. 关于iOS开发的各种证书

    关于iOS开发的各种证书 最近在接推送服务的时候,被各种证书弄得不亦晕乎,这里记录一下一些基本的证书作用: 1. App IDs appID分明确的和通配的两种,如果要使用推送功能,只能用明确的. 2 ...

  2. 文件包含漏洞(RFI)

    1文件包含漏洞简介 include  require  include_once   require_once RFI综述 RFI是Remote File Inclusion的英文缩写,直译过来就是远 ...

  3. 阿里云ECS下Ubuntu 16.04系统安装python3.6.5 环境并设置为默认

    一.添加python3.6安装包并安装: 二.修改系统默认python版本为3.6: 三.安装并升级pip版本: 一.添加python3.6安装包并安装: sudo apt-get install s ...

  4. Navicat和DBeaver的查询快捷键

    1.Navicat for MySQL(连接MySQL数据库的工具) ctrl + r 执行查询页中所有的sql语句 ctrl + shift + r 只运行选中的sql语句 2.DBeaver(支持 ...

  5. linux 学习总结---- mysql 总结

    用户的创建 ---->修改 ---->删除用户 create alter drop (数据定义语言 DDL) 授权: insert update delete grant *.* revo ...

  6. 对Java对象的认识与理解

    今天是我学习编程以来第一次写博客,记下平日学习所得,本来这几日都在学习web框架 但觉得梳理一下之前所学很有必要.毕竟之前学习Java感觉很粗略只是以考试为目的.所以就以<Thinking in ...

  7. kaldi HMM-GMM全部训练脚本分解

    目录 train_mono.sh train_deltas.sh train_lda_mllt.sh train_sat.sh train_mono.sh 单音素训练脚本: //初始化,[topo f ...

  8. 3.hadoop完全分布式搭建

    3.Hadoop完全分布式搭建 1.完全分布式搭建 配置 #cd /soft/hadoop/etc/ #mv hadoop local #cp -r local full #ln -s full ha ...

  9. HDU 1403 Longest Common Substring(后缀自动机——附讲解 or 后缀数组)

    Description Given two strings, you have to tell the length of the Longest Common Substring of them. ...

  10. Thunder团队——事后诸葛亮会议

    小组名称:Thunder 项目名称:爱阅APP 小组成员:王航 李传康 代秋彤 邹双黛 苗威 宋雨 胡佑蓉 杨梓瑞 一.设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型 ...