蓝魔法师

链接:

https://www.nowcoder.com/acm/contest/215/C

来源:牛客网

题目描述

“你,你认错人了。我真的,真的不是食人魔。”--蓝魔法师

给出一棵树,求有多少种删边方案,使得删后的图每个连通块大小小于等于\(k\),两种方案不同当且仅当存在一条边在一个方案中被删除,而在另一个方案中未被删除,答案对\(998244353\)取模

输入描述:

第一行两个整数\(n\),\(k\), 表示点数和限制

\(2 \le n \le 2000, 1 \le k \le 2000\)

接下来\(n-1\)行,每行包括两个整数\(u\),\(v\),表示\(u\),\(v\)两点之间有一条无向边

输出描述:

共一行,一个整数表示方案数对\(998244353\)取模的结果


长见识了,比赛交了\(8\)次最后终于过了。

树上分组背包,令\(dp_{i,j}\)代表子树\(i\)还剩余\(j\)个点可以连出去时的方案数。

这个转移每个人的写法都可以不一样,说一下我的。

初始化\(dp_{i,1}=1\),代表先强制选\(i\)

对每个子树做\(dp_{i,j}=dp_{s,k}\times dp_{i,j-k}\)表示连接

特判直接砍掉子树的情况,在做子树之前\(dp_{i,j}=dp_{i,j}\times dp_{s,0}\)

做完后再处理一下自己被砍的情况。

注意倒序枚举。

这样写出来是这样的。

void dfs(int now,int fa)
{
dp[now][1]=1;
siz[now]++;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa) continue;
dfs(v,now);
siz[now]+=siz[v];
for(int r=min(k,siz[now]);r;r--)
{
(dp[now][r]*=dp[v][0])%=mod;
for(int l=1;l<=min(r,siz[v]);l++)
(dp[now][r]+=dp[v][l]*dp[now][r-l])%=mod;
}
}
for(int i=1;i<=min(k,siz[now]);i++) (dp[now][0]+=dp[now][i])%=mod;
}

很不幸的是这样写可以轻松被链卡到\(O(n^3)\)


有一种写法是\(O(n^2)\)的

先枚举子树大小那么大,然后更新当前树

void dfs(int now,int fa)
{
dp[now][1]=1;
siz[now]++;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa) continue;
dfs(v,now);
for(int r=1;r<=min(k,siz[now]+siz[v]);r++)
f[r]=dp[now][r],(dp[now][r]*=dp[v][0])%=mod;
for(int l=1;l<=siz[v];l++)//物品
for(int r=min(k,siz[now]+l);r>=l+1;r--)//被转移的位置
(dp[now][r]+=dp[v][l]*f[r-l])%=mod;
siz[now]+=siz[v];
}
int rr=min(k,siz[now]);
for(int i=1;i<=rr;i++) (dp[now][0]+=dp[now][i])%=mod;
}

值得一提的是,这个跑法的复杂度是非常严格的,随机数据下进入核心转移的地方只有\(\frac{n(n-1)}{2}\)次,怎么构造都是这样(当然按不考虑\(k\)的大小的剪枝)

为什么呢?考虑一种感性的理解方式。

每一对点,当且仅当在它们的\(\tt{LCA}\)时,能够被转移。


考虑修补一下第一种做法,发现多余的转移是因为权值为\(0\),如果我们这样写,那么复杂度也是一样的了

void dfs(int now,int fa)
{
dp[now][1]=1;
siz[now]++;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(v==fa) continue;
dfs(v,now);
siz[now]+=siz[v];
for(int r=min(k,siz[now]);r;r--)
{
(dp[now][r]*=dp[v][0])%=mod;
if(r==1) continue;
for(int l=siz[v]-siz[now]+r;l<=min(min(k,r-1),siz[v]);l++)
(dp[now][r]+=dp[v][l]*dp[now][r-l])%=mod;
}
}
for(int i=1;i<=k;i++) (dp[now][0]+=dp[now][i])%=mod;
}

2018.10.27

牛客网 Wannafly挑战赛27 蓝魔法师的更多相关文章

  1. 牛客网 Wannafly挑战赛11 B.白兔的式子-组合数阶乘逆元快速幂

    链接:https://www.nowcoder.com/acm/contest/73/B来源:牛客网 B.白兔的式子   时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 262144K, ...

  2. 牛客网 Wannafly挑战赛9 C.列一列-sscanf()函数

      C.列一列   时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 262144K,其他语言524288K64bit IO Format: %lld 链接:https://www.now ...

  3. 牛客网Wannafly挑战赛25A 因子(数论 素因子分解)

    链接:https://www.nowcoder.com/acm/contest/197/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...

  4. 题解——牛客网Wannafly挑战赛23 B-游戏 (SG函数)

    前言 比赛的时候没学过SG函数的蒟蒻以为是道结论题,但是不是QwQ 和dummyummy巨佬一起推了快三个小时的规律 最后去问了真正的巨佬__stdcall __stdcall面带微笑的告诉我们,这是 ...

  5. 牛客网 Wannafly挑战赛8 B.LBJX的三角形

    B-LBJX的三角形 链接:https://www.nowcoder.com/acm/contest/57/B来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K, ...

  6. 牛客网 Wannafly挑战赛8 A.小Y和小B睡觉觉

    写了一会不想写了... A-小Y和小B睡觉觉 链接:https://www.nowcoder.com/acm/contest/57/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制: ...

  7. 牛客网 Wannafly挑战赛11 A.白兔的分身术

    水一水博客. 链接:https://www.nowcoder.com/acm/contest/73/A来源:牛客网 A.白兔的分身术     时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C ...

  8. 牛客网 Wannafly挑战赛9 A.找一找-数据处理

    好几天没好好学习了(咸鱼晒干了) 把稍微没那么咸鱼的几天前的一场牛客网的比赛稍微看了一下,菜的要死,这一场大数的比较多,都死了. A.找一找 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C ...

  9. 牛客网 Wannafly挑战赛 C 列一列 简单题 (题目有点坑)

    链接:https://www.nowcoder.com/acm/contest/71/C来源:牛客网 题目描述 小W在计算一个数列{An},其中A1=1,A2=2,An+2=An+1+An.尽管他计算 ...

随机推荐

  1. http tcp udp

    HTTP连接 1.HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用 ...

  2. 「日常训练」Duff in the Army (Codeforces Round #326 Div.2 E)

    题意(CodeForces 588E) 给定一棵\(n\)个点的树,给定\(m\)个人(\(m\le n\))在哪个点上的信息,每个点可以有任意个人:然后给\(q\)个询问,每次问\(u\)到\(v\ ...

  3. pyhon文件操作典型代码实现(非常经典!)

    1. 编写一个程序,统计当前目录下每个文件类型的文件数,程序实现如图: 实现代码: import os all_files = os.listdir(os.chdir("D:\\" ...

  4. Java开发工程师(Web方向) - 04.Spring框架 - 第1章.Spring概述

    第1章.Spring概述 Spring概述 The Spring Framework is a lightweight solution and a potential one-stop-shop f ...

  5. [SHELL]linux环境变量

  6. Django创建App报错

    在django下创建APP项目时遇到的坑 python manage.py startapp app01 报错内容如下: 解决:找到报错中的文件夹151行删除items(),)中的逗号即可 在命令行下 ...

  7. QT打开文件路径中含有中文和空格问题

    使用qt-mingw版做的软件,发给客户以后说工作不正常,配置文件无法打开,或者加载数据文件不正常.远程查看以后,发现客户经常将程序放置在中文带空格的路径下,导致文件打开不正常.所以最近想在程序上解决 ...

  8. NTP错误总结

    Ntp错误总结 解决ntp的错误 no server suitable for synchronization found 当用ntpdate -d 来查询时会发现导致 no server suita ...

  9. Keil sct分散加载文件

    官方说明:http://www.keil.com/support/man/docs/armlink/armlink_pge1401393372646.htm

  10. 20172333 2017-2018-2 《Java程序设计》第7周学习总结

    20172333 2017-2018-2 <Java程序设计>第7周学习总结 教材学习内容 1.继承是创建新类的快捷方式之一,继承可以使用父类的所有方法及对象. 2.继承具有单向性,父类不 ...