原题链接

Description

Ember和Storm正在玩游戏。首先,Ember构造一棵n个节点且每个节点度数不超过d的带节点编号的树T。然后,Storm选择两个不同的节点u和v,并写下从u到v路径上的节点编号,记为序列 a1, a2... a。最后,Ember在序列中选择一个位置 i(1 ≤ i < k),并在以下两个操作选择一个执行:

  • 翻转 ai+1... a并将这一段加上ai,操作后序列变为 a1, ... ai, ak + ai, ak-1 + ai, ... ai+1 + ai
  • 取负 ai+1... a并将这一段加上ai,操作后序列变为 a1, ... ai,  - ai+1 + ai,  - ai+2 + ai, ... - ak + ai

如果最后的序列是严格单调的,则Ember获胜,否则Storm获胜。

游戏情形可以用一个元组 (T, u, v, i, op) 来描述,op为翻转或是取负取决于Ember的决策。若Ember和Storm都使用最优策略(若有多种必胜策略,任选一种执行;若必败,也任选一种执行),试统计所有可能的游戏情形的数量,并输出其取模m的结果。

Input

仅一行,给出 n,d,m。 (2 ≤ n ≤ 200, 1 ≤ d < n, 1 ≤ m ≤ 2·109).

Output

输出一个数字——所有可能的游戏情形的数量取模m之后的结果。

首先,Ember一定会构造出一棵能让自己必胜的树。而Ember获胜当而仅当原序列$a$为单调的或是单峰的;且对于每一个合法的序列,有2种合法的$(i,op)$的组合。没有什么好证明的……在草稿纸上自己模拟一下两种操作就可以得到了。

问题转换为:统计满足以下条件的树的数量$S$:1. 包含$n$个节点,2. 每个节点度数不超过$d$,3. 树上任意两个节点间路径的编号序列为单调的或单峰的。最终答案为 $2\cdot n\cdot(n-1)\cdot S$ 。

而对于一棵合法的树,一定存在一个特殊点,满足以这个节点为起点或终点的所有路径都是单调的。为了方便统计,我们令合法树的根节点为特殊点。观察可得,对于一棵合法树,除根节点以外的子树都满足:父亲节点编号大于儿子编号,或是父亲编号小于儿子编号。所以我们只需要统计这两种情况的答案,然后在根节点处拼起来即可。而实际上,这两种情况是等价的。

令$f(i,j)$表示节点数为$i$,根节点度数为$j$,且父亲编号小于儿子编号的方案数。

枚举当前要拼接的子树大小$k$,钦定根节点编号最小,拼接过来的子树的根节点编号次小,可得到以下递推公式:

$$f(i,j)=\sum _{k=1}^{i-1}f(i-k,j-1)\cdot \binom{i-2}{k-1}\cdot \sum _{l=1}^{d-1}f(k,l)$$

令 $sum(i)=\sum _{j=1}^{d-1}f(i,j)$,可得:

$$f(i,j)=\sum _{k=1}^{i-1}f(i-k,j-1)\cdot \binom{i-2}{k-1}\cdot sum(k)$$

时间复杂度为 $O(n^{3})$ ,初始化 $f(1,0)=sum(1)=1$ 。

(这种方法是在评论区看到的……然后参考了一下wxh大爷的博客。官方题解给了另一种统计f数组的方式,要稍微复杂一些,以及因为不保证m是质数,会有一些细节需要处理。详见官方题解,细节处理详见评论区。)

统计出$f$数组后就可以开始拼接了,枚举满足父亲节点编号小于儿子编号的点数$i$、度数$j$, 满足父亲节点编号大于儿子编号的度数$k$,可得到以下公式:

$$S=\sum _{i=0}^{n-1}\sum _{j=0}^{d}\sum _{k=0}^{d-j}f(i+1,j)\cdot f(n-i,k)$$

而实际上一棵合法树是可以有多个合法根的,比如最简单的$n=2$的情况,合法根既可以是$1$也可以是$2$。我们可以得出另一个结论,如果一棵树有多个合法根,那么这些点一定构成一条单调链,一端是$j=1$且$k≠1$,另一端是$j≠1$且$k=1$,中间是$j=1$且$k=1$,我们把这棵树放在第一种情况统计。

得到最终公式:

$$S=\sum _{i=0}^{n-1}\sum _{j+k\leq d,k\neq 1}f(i+1,j)\cdot f(n-i,k)$$

代码如下:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int N=;
int n,d,mod;
LL ans,sum[N],c[N][N],f[N][N];
int main()
{
scanf("%d%d%d",&n,&d,&mod);
for(int i=;i<=n;i++)c[i][]=;
for(int i=;i<=n;i++)
for(int j=;j<=i;j++)
c[i][j]=(c[i-][j]+c[i-][j-])%mod;
sum[]=;f[][]=;
for(int i=;i<=n;i++)
{
for(int j=;j<=d;j++)
for(int k=;k<i;k++)
f[i][j]=(f[i][j]+f[i-k][j-]*sum[k]%mod*c[i-][k-]%mod)%mod;
for(int j=;j<=d-;j++)
sum[i]=(sum[i]+f[i][j])%mod;
}
for(int i=;i<=n-;i++)
for(int j=;j<=d;j++)
for(int k=;j+k<=d;k++)
if(k!=)ans=(ans+f[i+][j]*f[n-i][k]%mod)%mod;
printf("%lld",*n*(n-)*ans%mod);
return ;
}

【codeforces 914H】Ember and Storm's Tree Game的更多相关文章

  1. Codeforces 914H Ember and Storm's Tree Game 【DP】*

    Codeforces 914H Ember and Storm's Tree Game 题目链接 ORZ佬 果然出了一套自闭题 这题让你算出第一个人有必胜策略的方案数 然后我们就发现必胜的条件就是树上 ...

  2. 【CodeForces】914 H. Ember and Storm's Tree Game 动态规划+排列组合

    [题目]H. Ember and Storm's Tree Game [题意]Zsnuoの博客 [算法]动态规划+排列组合 [题解]题目本身其实并不难,但是大量干扰因素让题目显得很神秘. 参考:Zsn ...

  3. 【codeforces 415D】Mashmokh and ACM(普通dp)

    [codeforces 415D]Mashmokh and ACM 题意:美丽数列定义:对于数列中的每一个i都满足:arr[i+1]%arr[i]==0 输入n,k(1<=n,k<=200 ...

  4. 【codeforces 707E】Garlands

    [题目链接]:http://codeforces.com/contest/707/problem/E [题意] 给你一个n*m的方阵; 里面有k个联通块; 这k个联通块,每个连通块里面都是灯; 给你q ...

  5. 【codeforces 707C】Pythagorean Triples

    [题目链接]:http://codeforces.com/contest/707/problem/C [题意] 给你一个数字n; 问你这个数字是不是某个三角形的一条边; 如果是让你输出另外两条边的大小 ...

  6. 【codeforces 709D】Recover the String

    [题目链接]:http://codeforces.com/problemset/problem/709/D [题意] 给你一个序列; 给出01子列和10子列和00子列以及11子列的个数; 然后让你输出 ...

  7. 【codeforces 709B】Checkpoints

    [题目链接]:http://codeforces.com/contest/709/problem/B [题意] 让你从起点开始走过n-1个点(至少n-1个) 问你最少走多远; [题解] 肯定不多走啊; ...

  8. 【codeforces 709C】Letters Cyclic Shift

    [题目链接]:http://codeforces.com/contest/709/problem/C [题意] 让你改变一个字符串的子集(连续的一段); ->这一段的每个字符的字母都变成之前的一 ...

  9. 【Codeforces 429D】 Tricky Function

    [题目链接] http://codeforces.com/problemset/problem/429/D [算法] 令Si = A1 + A2 + ... + Ai(A的前缀和) 则g(i,j) = ...

随机推荐

  1. @getMapping与@postMapping

    首先要了解一下@RequestMapping注解. @RequestMapping用于映射url到控制器类的一个特定处理程序方法.可用于方法或者类上面.也就是可以通过url找到对应的方法. @Requ ...

  2. tqdm介绍及常用方法

    Tqdm 是一个快速,可扩展的Python进度条,可以在 Python 长循环中添加一个进度提示信息,用户只需要封装任意的迭代器 tqdm(iterator). 使用pip就可以安装. Tqdm 是一 ...

  3. golang json 读写配置文件

    package main import ( "encoding/json" "fmt" "os" ) type configuration ...

  4. zabbix优化,配合文件,zabbix_get命令

    一.配置文件优化 server端配置文件添加如下 StartPollers=160 #zabbix_server的进程数 StartPollersUnreacheable=80 #默认情况下,ZABB ...

  5. Mac进行 usr/bin 目录下修改权限问题,operation not permitted

    一般情况下我们在使用mac系统过程中下载一些文件.新建一些项目之后,这些文件都会默认是只读状态,这时我们只需要简单的一句权限设置命令就可以解决 你要修改文件上层目录的路径 但是我们在对 usr/bin ...

  6. Linux内核入门到放弃-页缓存和块缓存-《深入Linux内核架构》笔记

    内核为块设备提供了两种通用的缓存方案. 页缓存(page cache) 块缓存(buffer cache) 页缓存的结构 在页缓存中搜索一页所花费的时间必须最小化,以确保缓存失效的代价尽可能低廉,因为 ...

  7. Re:Exgcd解二元不定方程

    模拟又炸了,我死亡 $exgcd$(扩展欧几里德算法)用于求$ax+by=gcd(a,b)$中$x,y$的一组解,它有很多应用,比如解二元不定方程.求逆元等等,这里详细讲解一下$exgcd$的原理. ...

  8. 聊聊计算机中的编码(Unicode,GBK,ASCII,utf8,utf16,ISO8859-1等)以及乱码问题的解决办法

    作为一个程序员,一个中国的程序员,想来“乱码”问题基本上都遇到过,也为之头疼过.出现乱码问题的根本原因是编码与解码使用了不同而且不兼容的“标准”,在国内一般出现在中文的编解码过程中. 我们平时常见的编 ...

  9. codeforces#439 D. Devu and his Brother (二分)

    题意:给出a数组和b数组,他们的长度最大1e5,元素范围是1到1e9,问你让a数组最小的数比b数组最大的数要大需要的最少改变次数是多少.每次改变可以让一个数加一或减一 分析:枚举a数组和b数组的所有的 ...

  10. Spring 使用纯注解方式完成IoC

    目录 创建一个简单的Person类 使用xml方式配置Spring容器并获取bean的过程 创建xml配置文件 进行测试 使用纯注解方式配置Spring容器并获取bean的过程 创建spring配置类 ...