《训练指南》——6.10

Uva11174:

村民排队:村子里现在有n(1≤n≤40000)个人,有多少种方式可以把它们排成一列,使得没有人站在他父亲的前面(有些人的父亲可能不在村子里)?输入n和每个人的父亲编号,输出方案总数除以1000000007的余数。

分析:首先我们应该能够看到的是,这种有关家庭关系的图,需要借助基本的一个数据结构——树,但是这里由于各个祖先不同,会形成森林,但是为了更好处理,我们将森林中的根节点的上面构造一个虚拟根,记作v0,这样就形成了一棵树。

我们设f[i]是以节点vi为根,得到的排列情况书,即f[0]就是这道题目的答案。

那么我们现在来考察f[0]究竟怎么计算,这里用到基本的计数原理。我们假设虚拟根v0下有k个儿子v1、v2、v3…vk,相当于有k个家族,则我们可以通过如下的步骤得到f[0]:

(i)                 我们将每个家族的人视为一样的元素.

(ii)               得到排列数之后再乘上这个家族符合要求的排列数.

这里记s[i]是第i个家族的人数,也就是说以vi为根的所有节点的和(包括vi自己),那么完成第一个步骤,我们得到的方法数是

而完成第二个步骤,结合分步乘法原理,应该是如下的式子:

这样我们便得到了一个关于f[n]的递推式,如下:

其中k是v0的儿子个数,如果我们设置一个数组son[i]记录vi的儿子儿子数,ci表示节点的i个儿子在树结构中的序号,因此我们会得到更加具有普遍性的递推式子:

那么现在将②迭代到①当中,会发现一直递推下去,再考虑对于叶节点vj,有f[j]  = 1,因此我们能够得到如下的线性表达式:

那么基于这个线性表达式,接下来我们需要考虑的事情就很明了了:

问题一:如何基于树结构找到s[i]呢,这是最基本的数据结构的问题。

问题二:题目要求输出f[0] % mod,而根据数论当中同余运算的性质,涉及出发应该借助逆元,而结合mod的大小和s[i]的取值,有gcd(mod , s[i]),我们也是能够得到s[i]在关于mod下一定存在逆元的。

总结一下,这道题目还是一道非常好的题目的,它涉及了组合计数的基本原理、递推、整理数学公式、基本树形数据结构和数论当中的逆元,是一道非常综合的题目。这里笔者由于临近考试周时间紧张的原因,在如何编码实现计算s[i]和求解逆元上先不做讨论,以后有时间了再补充。

时间: 2024-08-28 19:06:18

《训练指南》——6.10的相关文章

《ACM国际大学生程序设计竞赛题解Ⅰ》——基础编程题

这个专栏开始介绍一些<ACM国际大学生程序设计竞赛题解>上的竞赛题目,读者可以配合zju的在线测评系统提交代码(今天zoj貌似崩了). 其实看书名也能看出来这本书的思路,就是一本题解书,简单暴力的通过题目的堆叠来提升解决编程问题的能力. 那么下面开始探索吧. zoj1037: BackgroundFor years, computer scientists have been trying to find efficient solutions to different computing p

《ACM国际大学生程序设计竞赛题解I》——6.10

Pku 1143: Description Christine and Matt are playing an exciting game they just invented: the Number Game. The rules of this game are as follows. The players take turns choosing integers greater than 1. First, Christine chooses a number, then Matt ch

《ACM国际大学生程序设计竞赛题解I》——6.11

pku 1107: Description Weird Wally's Wireless Widgets, Inc. manufactures an eclectic assortment of small, wireless, network capable devices, ranging from dog collars, to pencils, to fishing bobbers. All these devices have very small memories. Encrypti

《ACM国际大学生程序设计竞赛题解I》——6.8

Poj1068: Description Let S = s1 s2...s2n be a well-formed string of parentheses. S can be encoded in two different ways: q By an integer sequence P = p1 p2...pn where pi is the number of left parentheses before the ith right parenthesis in S (P-seque

2018 ACM 国际大学生程序设计竞赛上海大都会部分题解

题目链接 2018 ACM 国际大学生程序设计竞赛上海大都会 下午午休起床被同学叫去打比赛233 然后已经过了2.5h了 先挑过得多的做了 .... A题 rand x*n 次点,每次judge一个点位端点的共线向量数判断是否大于给定x 强行rand 500次 代码 #include<bits/stdc++.h> using namespace std; inline int read() { int x = 0,f = 1; char c = getchar(); while(c <

2018 ACM 国际大学生程序设计竞赛上海大都会赛

传送门:2018 ACM 国际大学生程序设计竞赛上海大都会赛 2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛2018-08-05 12:00:00 至 2018-08-05 17:00:00时长: 5小时 比赛情况 实录 难度差不多介于省赛和区域赛之间吧.开题A是计算几何,有点思路后就先放下去写签到题,B读错题WA一发,K直接套模板,然后就接着看A.之前写过类似题,没注意数据范围就头铁地交了发n3的代码,TE后才发现数据范围是之前那道十多倍,就听学长的先看D.推十分钟公式无果后打算直

第39届ACM国际大学生程序设计竞赛 亚洲区域赛(现场赛)西安站

 第39届ACM国际大学生程序设计竞赛 亚洲区域赛(现场赛)西安赛区总结报告 报告人:田思明 队名:ACpioneer 队长:陈志阳,队员:顾振兴,田思明 西安区域赛告下帷幕,我和陈志阳,顾振兴组成的ACpioneer队最终获得了一块宝贵的铜牌.首先要感谢陈志阳和顾振兴两位杰出队友的努力训练和出色表现,我作为一个新人跟着他们学到了很多很多,也十分珍惜和他们在一起的训练,比赛时光,其次要感谢陈志老师,不辞辛劳陪我们5队和6队前往西安参加比赛,还要感谢集训队所有曾经帮过我们的所有队员们,记得cdy

第39届ACM国际大学生程序设计竞赛大陆地区赛站奖励方案

搬砖: 为了更好地吸引优秀选手参加第39届ACM国际大学生程序设计竞赛,全球赞助商的经费用于参赛队服和赛事的承办活动,中国赛区赞助商提供的经费用于优秀参赛队的奖励(包括奖金.奖牌.奖杯.获奖证书及奖品等), 竞赛命题,参赛手册,竞赛宣传方面的费用支出.每个赛区的具体奖励方式如下: 设冠军.亚军.季军三座奖杯,分别颁发奖金5000.3500.2000元人民币: 设15名金奖(包括冠.亚.季军)和30名银奖, 铜奖数量为参赛队数的30%: 获金奖的队(未获奖杯的队)每队颁发奖金1000元人民币; 获

2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 A Fruit Ninja

传送门 题解:给你一堆点问你能不能找出一条直线,使其穿过的点大于n*x. 题解:想起某道CF题目,给你一堆点问你能不能找出两条直线使其穿过所有的点.当时就是在一定时限内随机找了两个点,再枚举每个点是否满足,如果超过该时限仍然不满足则直接返回no.这题也是一样的做法,直接随机两个点,再枚举过去.因为x为0.1到0.9,所以如果所给数据满足条件,那么它有极大概率能够跑出结果.4发只有一次超时 #include<bits/stdc++.h> //CLOCKS_PER_SEC #define se s

2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛-K-Matrix Multiplication(矩阵乘法)

题目描述 In mathematics, matrix multiplication or matrix product is a binary operation that produces a matrix from two matrices with entries in a field, or, more generally, in a ring or even a semiring. The matrix product is designed for representing the