牛客网 Wannafly挑战赛27 蓝魔法师
蓝魔法师
链接:
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 蓝魔法师的更多相关文章
- 牛客网 Wannafly挑战赛11 B.白兔的式子-组合数阶乘逆元快速幂
链接:https://www.nowcoder.com/acm/contest/73/B来源:牛客网 B.白兔的式子 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 262144K, ...
- 牛客网 Wannafly挑战赛9 C.列一列-sscanf()函数
C.列一列 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 262144K,其他语言524288K64bit IO Format: %lld 链接:https://www.now ...
- 牛客网Wannafly挑战赛25A 因子(数论 素因子分解)
链接:https://www.nowcoder.com/acm/contest/197/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...
- 题解——牛客网Wannafly挑战赛23 B-游戏 (SG函数)
前言 比赛的时候没学过SG函数的蒟蒻以为是道结论题,但是不是QwQ 和dummyummy巨佬一起推了快三个小时的规律 最后去问了真正的巨佬__stdcall __stdcall面带微笑的告诉我们,这是 ...
- 牛客网 Wannafly挑战赛8 B.LBJX的三角形
B-LBJX的三角形 链接:https://www.nowcoder.com/acm/contest/57/B来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K, ...
- 牛客网 Wannafly挑战赛8 A.小Y和小B睡觉觉
写了一会不想写了... A-小Y和小B睡觉觉 链接:https://www.nowcoder.com/acm/contest/57/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制: ...
- 牛客网 Wannafly挑战赛11 A.白兔的分身术
水一水博客. 链接:https://www.nowcoder.com/acm/contest/73/A来源:牛客网 A.白兔的分身术 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C ...
- 牛客网 Wannafly挑战赛9 A.找一找-数据处理
好几天没好好学习了(咸鱼晒干了) 把稍微没那么咸鱼的几天前的一场牛客网的比赛稍微看了一下,菜的要死,这一场大数的比较多,都死了. A.找一找 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C ...
- 牛客网 Wannafly挑战赛 C 列一列 简单题 (题目有点坑)
链接:https://www.nowcoder.com/acm/contest/71/C来源:牛客网 题目描述 小W在计算一个数列{An},其中A1=1,A2=2,An+2=An+1+An.尽管他计算 ...
随机推荐
- python学习五
打包代码与数据 数据结构要与数据匹配,数据结构影响代码的复杂性 列表 集合 字典 #创建与初始化 cleese={} cleese2=dict() cleese["name"] ...
- Qt 计算两个日前间隔天数
某一个大神写的 改写了一点 请无视注释 //时间计算法则 /********************************************************************** ...
- 在deepin系统中制作桌面快捷方式
在使用deepin-wine 安装一些软件的时候,每次启动都需要到.deepinwine目录下运行deepin-wine xx.exe.笔者在安装过HeidiSql之后,一直苦于这种情况.比较好的解决 ...
- TW实习日记:第24-25天
项目的交付期是真的赶...一直在不断地修改一些小bug,然后消息推送功能出了一个问题,就是不知道为什么PC端会发送两次消息到移动端后台.其中第一条正常第二条会有乱码不正常,可以说是很奇怪了,一开始都认 ...
- js设计模式:工厂模式、构造函数模式、原型模式、混合模式
一.js面向对象程序 var o1 = new Object(); o1.name = "宾宾"; o1.sex = "男"; o1.a ...
- JAVA基础学习之路(三)类定义及构造方法
类的定义及使用 一,类的定义 class Book {//定义一个类 int price;//定义一个属性 int num; public static int getMonney(int price ...
- Python入门(5)
导览: 函数 集合 迭代器与生成器 模块 一.函数 只要学过其他编程语言应该对函数不太陌生,函数在面向过程的编程语言中占据了极重要的地位,可以说没有函数,就没有面向过程编程,而在面向对象语言中,对象的 ...
- 隐马尔科夫模型(hidden Markov Model)
万事开头难啊,刚开头确实不知道该怎么写才能比较有水平,这篇博客可能会比较长,隐马尔科夫模型将会从以下几个方面进行叙述:1 隐马尔科夫模型的概率计算法 2 隐马尔科夫模型的学习算法 3 隐马尔科夫模型 ...
- [leetcode-779-K-th Symbol in Grammar]
On the first row, we write a 0. Now in every subsequent row, we look at the previous row and replace ...
- HDU 1042 N!(高精度乘)
Problem Description Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N! Input One N in ...