鬼能想到的dp定义:dp[i][j]表示在一棵i级超级树中,有j条路径同时存在且这j条路径没有公共点时,可能的情况数

刚开始我也没看懂,所以举个例子

如一个2级的超级树,父节点为1,左右儿子为2,3

(感谢Al_Ca贡献的图,但我感觉题目里给的这个带编号更好一些。懒得把字去掉了将就着看吧)

(感谢xkl贡献的截好的图,但我斟酌了一下带上样例解释你们是不是会更好理解啊~)

(我太挑剔啦,不用给我发图啦,谢谢大家)

dp[2][1]=9,因为2级树里的路径一共有9条(样例),显然只有一条路径的话肯定没有公共点

dp[2][2]=7,(1,2)(1,3)(2,3)(2,13)(2,31)(3,12)(3,21),注意路径方向不同就是不同的

//公告:原数有误,感谢starsing边骂我边更正

dp[2][3]=1,只有(1单独作为一条路径,2单独作为一条路径,3单独作为一条路径,共3条)这一种可能。它们没有公共点。

dp[2][4]=0,2级树只有3个点,每条路径至少1个点,所以4条路径不可能没有公共点

那么按照套路。。。递推肝它!

如果你想要得到dp[i][j],该从什么转移过来?

情况太多了,想不出来。。。

我们尝试把dp[i][j]的情况设为已知,往后推别的

把两棵i-1级的树,配上一个根节点,合成一个i级的树,合成过程中的方案?

枚举左右子树中各有多少路径,左子树j右子树k,设sum=dp[i][j]*dp[i][k]

首先,想最简单的玩意:与根节点无关,左右子树保持原样

那么整个图中的路径数并没有变,左子树还是j个,右子树k个,只不过整个树升级了,根据乘法原理

dp[i+1][j+k]+=dp[i][j]*dp[i][k],即dp[i+1][j+k]+=sum,就这样累加方案数就好了

下一种情况,你随便从左子树里选一条边,把这条边的终点和父节点相连,相连之后的新路径仍然与右子树当中的任何一条路径没有交点

左边的路径增长了1,但是路径的总数没有变,还是(左子树+根)有j条,右子树有k条,从左子树j个里挑出一个的方案数是j

dp[i+1][j+k]+=sum*j;    ----(2-1-1)

然后我们既然可以把终点延伸到父节点,我们也可以把起点延伸到父节点

我们还是从左子树中随便挑路径,把根节点连向它,同上,路径延长而总数不变

dp[i+1][j+k]+=sum*j;    ----(2-2-1)

你现在一直是在左子树里挑边,为什么不在右子树里也挑呢?全部同理。不过是j变成了k

dp[i+1][j+k]+=sum*k;    ----(2-1-2)

dp[i+1][j+k]+=sum*k;    ----(2-1-2)

合并2打头的这四个式子:dp[i+1][j+k]+=2*sum*(j+k);

考虑下一种情况:左子树有j条右子树有k条,可是父节点它本身还是一条啊

那么总路径数就是(左j+右k+根1)=j+k+1

dp[i+1][j+k+1]+=sum;

再下一种情况:我们从左子树中选出一条路径,把它的终点连向父节点,在从根节点连向右子树的一条路径的起点

总路径数是j+k-1,因为你把两条合成了一条

还是举例子,若左子树有三条路径ABC,右子树3条abc。合成A和根再到a,现在的路径就是A-a, B, C, b, c,为3+3-1=5条。

而选边的方法数是j*k,这个是左连根再连右。同理还有右连根再连左,所以总数*2.

dp[i+1][j+k-1]+=sum*2*j*k;

最后一种情况,也是最恶心的:左子树一条路径终点连向父节点,再由父节点连向左子树的另一条路径的起点

证明可行性:因为dp含义中已经定义,这些路径彼此没有交点,那么从中任选两条路径后,与根节点按上述方法相连后仍然这一条路径自身没有公共点,与其他边仍然没有交点,满足条件。

dp[i+1][j+k-1]+=sum*j*(j-1)  (5-1)

因为是要在l条路径中选出两条不一样的,且与顺序有关不用除2

(你可以认为是选出的第一个路径的起点作为合成路径的起点,第二条路径的终点作为合成路径的终点,那么交换这两条路径所得到的合成路径是不同的)

同理,从右边选两条:dp[i+1][j+k-1]+=sum*k*(k-1)  (5-2)

合并一下:dp[i][j+k-1]+=sum*(j*(j-1)+k*(k-1));

好了,没有其他情况了。5个蓝色的式子就是全部的递推式子,不重不漏。

初始状态dp[1][0]=dp[1][1]=1;

最后的答案就是dp[n][1]了,即n级树中全部的路径数,没有相交之类的限制(所以第二维选出一条路径即可)

一定一定要多取模!

完事!

但是你A不了,对不对?

主要有两种错误,稍讲一下。

TLE :里面可能夹杂了WA,真的。

卡常,加法的取模优化,这还不够。但是有必要!

你仔细想一下枚举范围,i肯定是到n了,那么j和k呢?

能给dp[m][q]贡献答案的,是dp[m-1][?],问号如果是大于q+1,显然就没用了。即两维之和不超过m+q

所以为了求出dp[n][1],那么两维之和就不必超过n+1。所以对j的限制就是0~(n-i+2)

那么对k的限制就更紧了,0~(n-i+2-j)

还是不够?前期的某些枚举是无效的,如k=300,你会枚举到dp[1][250]之类的

1级树里怎么可能会有250条路径嘛!

因此对枚举的上届再次限制,在满足上一个条件的前提下,还要限制j.k<=2i-1

顺便再提一下zkt的常数减半的优化:因为j和k同步的枚举,颠倒它们的顺序会累加完全一样的答案

那么就干脆把sum加倍,强制k从j+1开始枚举,特殊处理j==k即可。

WA 95了?(或者因为有T的点被显示成了WA60之类)

友情赠送测试点“1 1”

我并没有经历这个问题,因为我输出的时候顺手取模了。

不要小瞧这5分!这很关键!要长记性!

然而。。。有一个最重要问题没有解决,这个思路是怎么想到的?在题解的开头我说它很难想到。

可是“如何想到”这很关键! 否则你只会看到别人的dp定义才会做,考试还是什么也不会。

思维这个东西很难讲清楚,但我还是要冒险说一说。[不喜勿喷]

至少,i级树从i-1级树中推来的这个分解问题这个思路应该还是能够想到的吧?

那么从这个角度出发分情况,应该是可以想到上述5种情况的。

在要用父节点拼接两条路径时,我们可以发现如果设的dp含义中如果不限制让它没有公共点,那么拼接起来无法计算!

这样也许就会可以想到了吧。。。反正我没想到。。。还要加油啊

接下来含义中已经定义了没有交点。

我们观察数据范围,应该是n3左右的,最外层枚举树的等级没什么问题,里面呢?

我们将样例输出2即245分解质因数(常用思路),发现出现了较大的质数,猜测这题不是简单粗暴的相乘,而是某些东西相乘再求和

这样我们就有了一个大体的框架(当然到这时候你还想不到限制枚举范围什么的)

 for(int i=;i<n;++I)//表示树的等级
for(int j=;j<=n;++j)//含义未知
for(int k=;k<=n;++k)//含义未知
dp[i+][?]+=dp[i-][j]*dp[i-][k]*(?);

现在我们只需要猜测出那两个位置的含义是什么,式子中的问号就能凿实了。

还有什么的限制是n级别的?说实在的我的第一反应是已经用在路径中的点的数量。

但是我们可以发现每个点之间并不是平等的,它们的连边关系不同,故笼统地用它们的数量来推是不现实的。

点不行,还能是啥?只能是边了,而且没有交点。说真的,不太好想。

但是边之间的确彼此平等。。。枚举范围的确是n级别。。。

所以你就想到了。。。

好吧,我承认,有点牵强,但是的确有人能在考场上自己想出来,他们太强了,所以咱们更要练啊!

最后,给一个建议,看完了博客去打题之前,你最好再系统地理解一下,争取码代码的时候不要再回来看公式。

自己根据含义想出来,自己推式子,理解消化,做题才有意义。

记住,你不是公式的搬运工。

最后送给你们几个调试用小样例(不取模)

1 1

2 9

3 245

4 126565

5 32054326261

 #include<cstdio>
#include<iostream>
using namespace std;
#define int long long
#define sum (dp[i][l]*dp[i][r])%mod
int dp[][],n,k,mod;
inline void modd(long long &a){if(a>=mod)a-=mod;}
signed main(){
scanf("%lld%lld",&n,&mod);
dp[][]=dp[][]=;
for(int i=;i<n;++i) for(int l=;l<=min(n-i+,i<=?(1ll<<i)-:n-i+);++l) for(int r=;r<=min(n-i+-l,i<=?(1ll<<i)-:n-i+);++r){
modd(dp[i+][l+r]+=sum);//直接转移
modd(dp[i+][l+r+]+=sum);//只多了一个根自己是路径
modd(dp[i+][l+r]+=(sum<<)*(l+r)%mod);//只把一条边伸长到根节点,双向
modd(dp[i+][l+r-]+=l*r%mod*(sum<<)%mod);//左右通过根节点相连
modd(dp[i+][l+r-]+=sum*(l*(l-)%mod+r*(r-)%mod)%mod);//同侧通过根节点相连
}
printf("%lld\n",dp[n][]%mod);
}

考时垃圾,考后牛逼。。。有什么用

[07/18NOIP模拟测试5]超级树的更多相关文章

  1. [7.18NOIP模拟测试5]砍树 题解(数论分块)

    题面(加密) 又考没学的姿势……不带这么玩的…… 考场上打了个模拟 骗到30分滚粗了 稍加思考(滑稽)可将题面转化为: 求一个最大的$d$,使得 $\sum \limits _{i=1}^n {(\l ...

  2. 【NOIP模拟赛】超级树 DP

    这个题我在考试的时候把所有的转移都想全了就是新加一个点时有I.不作为II.自己呆着III.连一个IV.连接两个子树中的两个V连接一个子树中的两个,然而V我并不会转移........ 这个题的正解体现了 ...

  3. [CSP-S模拟测试]:Walk(树的直径+数学)

    题目描述 给定一棵$n$个节点的树,每条边的长度为$1$,同时有一个权值$w$.定义一条路径的权值为路径上所有边的权值的最大公约数.现在对于任意$i\in [1,n]$,求树上所有长度为$i$的简单路 ...

  4. [CSP-S模拟测试]:柱状图(树状数组+二分+三分)

    题目描述 $WTH$获得了一个柱状图,这个柱状图一共有$N$个柱子,最开始第$i$根柱子的高度为$x_i$,他现在要将这个柱状图排成一个屋顶的形状,屋顶的定义如下:$1.$屋顶存在一个最高的柱子,假设 ...

  5. [CSP-S模拟测试]:count(树分块)

    题目描述 李华终于逃离了无尽的英语作文,重获自由的他对一棵树产生了兴趣.首先,他想知道一棵树是否能分成大小相同的几块(即切掉一些边,使得每个连通块的点数相同).然后,他觉得这个问题过于简单,于是他想知 ...

  6. [CSP-S模拟测试]:影魔(树状数组+线段树合并)

    题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...

  7. [CSP-S模拟测试]:统计(树状数组+乱搞)

    题目传送门(内部题120) 输入格式 第一行,两个正整数$n,m$. 第二行,$n$个正整数$a_1,a_2,...,a_n$,保证$1\leqslant a_i\leqslant n$,可能存在相同 ...

  8. [7.18NOIP模拟测试5]星际旅行 题解

    题面(加密) 考场上靠打表yy出的规律进而想到的正解233333 可以把一条双向边拆成两条单向边,这样的话每个点度数都为偶数,符合欧拉图的定义. 那么题目可以转化为:去掉两条边,使图中存在一条欧拉路. ...

  9. 「题解」:07.18NOIP模拟赛T1:星际旅行

    问题 A: 星际旅行 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 考试心路历程 拿到这道题感觉很懵逼,所以先搞的T2和T3,最后码了个暴力,结果还不如直接输出‘0’得分高 ...

随机推荐

  1. asp.net core 自定义中间件【以dapper为例】

    在asp.net core开发中.按照国际案例开始.都是先在Nuget安装XXX包.比如我们今天要用到的Dapper nuget里面安装Dapper 1.然后新建一个类文件DapperExtensio ...

  2. Java 从入门到进阶之路(八)

    在之前的文章我们介绍了一下 Java 中的重载,接下来我们看一下 Java 中的构造方法. 我们之前说过,我们在定义一个变量的时候,java 会为我们提供一个默认的值,字符串为 null,数字为 0. ...

  3. 常见的javascript跨站

    第一类: <img src=javascript:alert() /> <iframe src=javascript:alert()></iframe> <s ...

  4. 网页布局——grid弹性网格布局

    网格布局(Grid)是最强大的 CSS 布局方案. Flexbox 是为一维布局设计的,而 Grid 是为二维布局设计. grid目前兼容性目前还可以,主流浏览器对它的支持力度很大,ie9,10宣布它 ...

  5. 爬虫之beautifulsoup篇之一

    一个网页的节点太多,一个个的用正则表达式去查找不方便且不灵活.BeautifulSoup将html文档转换成一个属性结构,每个节点都是python对象.这样我们就能针对每个结点进行操作.参考如下代码: ...

  6. SecureCRT连接虚拟机下的CentOS7

    1.首先在VMWare下配置CentOS为桥接模式: 2.查看本机ip: 3.ip addr查看centos的mac地址: 4.在root权限下修改/etc/sysconfig/network-scr ...

  7. Unreal Engine 4 系列教程 Part 2:蓝图教程

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  8. 流包装器实现WebShell免杀

    说明: 本文首发自 https://www.secpulse.com/archives/73391.html ,转载请注明出处. 前言 本文是看PHP使用流包装器实现WebShell有感,权当做个笔记 ...

  9. css 动画animation基本属性(干货)

    /* 动画名称 */ animation-name: cloud; /* 属性定义动画完成一个周期所需要的时间,以秒或毫秒计 */ animation-duration:1s; /* 属性定义动画何时 ...

  10. Python开发【第一篇】:目录

    本系列博文包含Python基础.前端开发.Web框架.缓存以及队列等,希望可以给正在学习Python编程的朋友们提供一点帮助! .Python开发[第一篇]:目录 .Python开发[第二篇]:初始P ...