省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)


一
稍微转化一下,就是找所有和原树差距不超过k的不同构树的个数
一个挺trick的想法是:
由于矩阵树定理的行列式的值是把邻接矩阵数值看做边权的图的所有生成树的边权乘积之和
那么如果把不存在于原树中的边的边权设为x,做矩阵树定理得到n-1次的多项式第i次项系数就是选择新选择i个边的方案数!
带着x不好做,x=1~n带入,然后插值即可
O(n^4)
二
开始碾标算了:
还是可以树形DP,经典的树形DP套路难办的原因是不知道干掉的子树接在哪里
所以我们干脆先不管接在哪里,先都砍断
一个公式:
https://rqy.moe/Solutions/bzoj5475/
证明导数第二步有点生成函数的思想了
对于拆成k个连通块,方案数可以直接算
设f[i][j][k],以i为根子树保留j条边,和i相连的连通块sz为k的方案数。枚举子树保留边数和sz就可以愉快转移了
但是会算重
如果直接乘上n^(k-2)可能会把断的边连回去,不止保留了j个,并且同一个方案可能因为保留的不同的j个计算多次!
不慌不慌
一切都是因为实际上可能连回去保留了不止j个,我们钦定了j个,其他随便选的方案数是f,
枚举具体保留了几个,可以二项式反演
$f[t]=\sum_{k=t}^{n} C(k,t)*ans[k]$
ans表示恰好保留了k个
没了
O(n^3)
三
进一步优化!
$\Pi a_i$有组合意义,就是对于k个连通块,我们每个连通块恰好选择一个点的方案数!
f[i][j][0/1],表示,,,,,i这个连通块内有没有选择点,总方案数
愉快转移,断边必须y选择。
代码
:
#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=;
const int mod=;
int n,k;
int qm(int x,int y){
int ret=;while(y){
if(y&) ret=(ll)ret*x%mod;x=(ll)x*x%mod;
y>>=;
}return ret;
}
struct node{
int nxt,to;
}e[*N];
int hd[N],cnt;
int ad(int x,int y){
return x+y>=mod?x+y-mod:x+y;
}
void add(int x,int y){
e[++cnt].nxt=hd[x];
e[cnt].to=y;
hd[x]=cnt;
}
int sz[N];
int f[N][N][];
int C[N][N];
ll ans[N],dp[N];
void dfs(int x,int fa){
sz[x]=;
f[x][][]=f[x][][]=;
int g[][N][];
memset(g[],,sizeof g[]);
//memset(g,0,sizeof g);
g[][][]=g[][][]=;
int tmp=;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa) continue;
dfs(y,x);
tmp^=;
//for(reg j=0;j<sz[x]+sz[y];++j) g[tmp][j][0]=g[tmp][j][1]=0;
memset(g[tmp],,sizeof g[tmp]);
for(reg j=;j<sz[x];++j){
for(reg k=;k<sz[y];++k){
g[tmp][j+k][]=ad(g[tmp][j+k][],(ll)g[tmp^][j][]*f[y][k][]%mod);
g[tmp][j+k][]=ad(g[tmp][j+k][],(ll)g[tmp^][j][]*f[y][k][]%mod); g[tmp][j+k+][]=ad(g[tmp][j+k+][],(ll)g[tmp^][j][]*f[y][k][]%mod);
g[tmp][j+k+][]=ad(g[tmp][j+k+][],ad((ll)g[tmp^][j][]*f[y][k][]%mod,(ll)g[tmp^][j][]*f[y][k][]%mod));
}
}
sz[x]+=sz[y];
}
//cout<<" f "<<x<<endl;
for(reg j=;j<sz[x];++j) {
f[x][j][]=g[tmp][j][],f[x][j][]=g[tmp][j][];
//cout<<j<<" n0 "<<" : "<<f[x][j][0]<<" n1 "<<f[x][j][1]<<endl;
}
}
int main(){
rd(n);rd(k);
if(k==){
puts("");return ;
}
int x;
for(reg i=;i<=n;++i){
rd(x);++x;
add(i,x);add(x,i);
}
dfs(,);
for(reg j=;j<n;++j) {
if(j!=n-) dp[j]=(ll)f[][j][]*qm(n,n-j-);
else dp[j]=;
}
ans[n-]=dp[n-];
C[][]=;
for(reg i=;i<=n;++i){
C[i][]=;
for(reg j=;j<=n;++j){
C[i][j]=(C[i-][j-]+C[i-][j])%mod;
}
}
ll op=ans[n-];
for(reg i=n-;i>=n-k-;--i){
// cout<<" ii "<<i<<" : "<<dp[i]<<endl;
for(reg j=i+;j<n;++j){
dp[i]=(dp[i]+mod-(ll)C[j][i]*ans[j]%mod)%mod;
}
ans[i]=dp[i];
op=(op+dp[i])%mod;
}
printf("%lld",op);
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2019/3/4 19:02:40
*/
思路:
矩阵树:新加k条新边,为了控制边数,所以用x表示边权得到方案数,插值也很漂亮
DP:直接DP难写,受prufer序列的推论启发,考虑对于连通块直接统计,然后二项式反演去重,
组合意义的优化,类似于:[NOI2009]管道取珠
省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)的更多相关文章
- 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解
今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...
- @省选模拟赛03/16 - T3@ 超级树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...
- 3.28 省选模拟赛 染色 LCT+线段树
发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...
- NOI2019省选模拟赛 第五场
爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...
- NOI2019省选模拟赛 第六场
传送门 又炸了-- \(A\) 唐时月夜 不知道改了什么东西之后就\(A\)掉了\(.jpg\) 首先,题目保证"如果一片子水域曾经被操作过,那么在之后的施法中,这片子水域也一定会被操作&q ...
- 省选模拟赛 arg
1 arg (arg.cpp/in/out, 1s, 512MB)1.1 Description给出一个长度为 m 的序列 A, 请你求出有多少种 1...n 的排列, 满足 A 是它的一个 LIS. ...
- 5.10 省选模拟赛 拍卖 博弈 dp
LINK:拍卖 比赛的时候 前面时间浪费的有点多 写这道题的时候 没剩多少时间了. 随便设了一个状态 就开始做了. 果然需要认真的思考.其实 从我的状态的状态转移中可以看出所有的结论. 这里 就不再赘 ...
- 5.5 省选模拟赛 B Permutation 构造 贪心
LINK:Permutation 对于这种构造神题 我自然是要补的.为啥就我没想出来哇. 30分还是很好写的 注意8!实际上很小 不需要爆搜 写bfs记录状态即可.至于判断状态是否出现与否 可以开ma ...
- 省选模拟赛 4.26 T1 dp 线段树优化dp
LINK:T1 算是一道中档题 考试的时候脑残了 不仅没写优化 连暴力都打挂了. 容易发现一个性质 那就是同一格子不会被两种以上的颜色染.(颜色就三种. 通过这个性质就可以进行dp了.先按照左端点排序 ...
随机推荐
- 【JVM.2】垃圾收集器与内存分配策略
垃圾收集器需要完成的3件事情: 哪些内存需要回收? 什么时候回收? 如何回收? 在前一节中介绍了java内存运行时区域的各个部分,其中程序计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭:栈 ...
- ABP+AdminLTE+Bootstrap Table权限管理系统第十一节--Bootstrap Table用户管理列表以及Module Zero之用户管理
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 用户实体 用户实体代表应用的一个用户,它派生自AbpUser类,如下所示: public class User : ...
- asp.net mvc接收安卓post的json字符串
筛选器: using System; using System.Collections.Generic; using System.Linq; using System.Web; using Syst ...
- shell脚本之特殊符号总结性梳理
# 井号 (comments) 这几乎是个满场都有的符号#!/bin/bash 井号也常出现在一行的开头,或者位于完整指令之后,这类情况表示符号后面的是注解文字,不会被执行. # This line ...
- Individual Project 1 总结
题目: http://www.cnblogs.com/jiel/p/3978727.html 1. 估计时间: ① 遍历目录找到所有文本文件 3天 ② 编写统计词频的函数 排序的函数 并输出到文件 2 ...
- 【MOOC EXP】Linux内核分析实验七报告
程涵 原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 可执行程序的装载 知识点梳理 一.预处 ...
- html5制作导航条
(1)background-repeat:no-repeat;图片不平铺 (2)使用<ul>和<li>便签,代码简介有序.易于编排. (3)在引入外部css文件时,<li ...
- 使用thinkphp框架实现Excel导入数据库
之前讲过php实现Excel导出数据库的随笔,链接:https://www.cnblogs.com/nuanai/p/6727711.html 之前的项目用到较多的就是Excel导出,现在用到了Exc ...
- ios开发之--CAKeyframeAnimation的详细用法
简单的创建一个带路径的动画效果,比较粗糙,不过事先原理都是一样的, 代码如下: 1,创建动画所需的view -(void)creatView { moveView = [UIView new]; mo ...
- String系列-----AbstractStringBuilder
1. AbstractStringBuilder是StringBuffer和StringBuilder的父类 package com.amazing.jdk.string_2017_12_31; im ...