蓝魔法师

链接:

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. mysql源码

    从代码的角度来说,没有丝毫设计感,尤其是优化器部分.不过那些是常年累积的原因,一些新加较独立的部分,设计的就很舒服,真正的面向对象做法.

  2. ASP.NET数据库连接

    启动Visual Studio,新建一个web工程 点开工程目录下web.config文件, 找到节点,新增数据库配置 aspx界面新建一个button和一个文本框用于测试数据库连接, 其中butto ...

  3. 「专题训练」Hard problem(Codeforces Round #367 Div. 2 C)

    题意与分析 题意:给出\(n\)个字符串,可以反转任意串,反转每个串都有其对应的花费\(c_i\).经过操作后是否能满足字符串\(\forall i \in [1,n] \text{且} i \in ...

  4. 「题目代码」P1054~P1059(Java)

    P1054 猴子吃桃 import java.util.*; import java.io.*; import java.math.BigInteger; import java.lang.Chara ...

  5. 创建并运行第一个Django项目

    首先, 添加Django模块: 在CMD命令行输入 python -m django --version 查看Django版本: 创建第一个Django项目: 整个工程的目录结构: mysite目录是 ...

  6. JMeter 录制APP脚本

    具体步骤: 1.启动JMeter: 2.在“测试计划”中添加“线程组”: 3.“工作台”中添加“HTTP代理服务器”: 4.配置代理服务器:端口:8888(默认值),HTTPS Domains:192 ...

  7. 6.2 element和elements

    为什么这个要单独拿出来说,因为我在很多群里面看见很多人不能区分这个! 因为之前的包有点问题,另外后续还会更换app,因为部分app可能没有符合的案例场景,我需要找到那个场景给大家做个实例..便于大家跟 ...

  8. ASP.NET中Gridview一些技巧

    ASP.NET中Gridview一些技巧 一.后台覆盖掉Gridview中自动填充的值 我们可以再Gridview中的事件触发的过程中修改其中的值,而这些值将会在具体的运行过程中覆盖掉那些自动属性.这 ...

  9. 缓存 memcache 小白笔记

    W: Memcached是神魔? Q:Memcached是一个自由开源的,高性能,分布式内存对象缓存系统. W:原理图 Q:如下 1浏览器    2 服务器   3  数据库    4  memcac ...

  10. OpenMPI源码剖析1:MPI_Init初探

    OpenMPI的底层实现: 我们知道,OpenMPI应用起来还是比较简单的,但是如果让我自己来实现一个MPI的并行计算,你会怎么设计呢?————这就涉及到比较底层的东西了. 回想起我们最简单的代码,通 ...