题意:nnn 个点的带点权的树,点权最大值为 www,求所有连通子图第 kkk 大权值之和模 641236412364123。

n,w≤1666n,w\leq 1666n,w≤1666,时限 5s。

idea 很好的题,可惜被暴力艹过去了。

首先如果点权只有 000 和 111,我们相当于求包含至少 kkk 个 111 的连通子图个数。可以设 f(u,k)f(u,k)f(u,k) 表示 uuu 为根的可空连通子图中有恰好 kkk 个 111 的数量,然后就是刻在 DNA 里的转移方程

f(u,k)⟵∑i=0kf(u,i)g(v,k−i)f(u,k)\longleftarrow\sum_{i=0}^kf(u,i)g(v,k-i)f(u,k)⟵i=0∑k​f(u,i)g(v,k−i)

f(u,0)⟵f(u,0)+1f(u,0)\longleftarrow f(u,0)+1f(u,0)⟵f(u,0)+1

边界: f(u,valu)=1f(u,val_u)=1f(u,valu​)=1

我们枚举值域,大于等于的设为 111,小于的设为 000,算出方案数乘上差值,就可以 O(n2w)\Omicron(n^2w)O(n2w) 踩标算了。

注意到这个转移方程是卷积的形式,所以可以写成生成函数

fu(x)=∏v∈son(u)fv(x)+1f_u(x)=\prod_{v\in son(u)}f_v(x)+1fu​(x)=v∈son(u)∏​fv​(x)+1

然后你要求所有点的和,所以开个 ggg 顺便记一下

gu(x)=∑v∈son(u)gv(x)+fu(x)−1g_u(x)=\sum_{v\in son(u)}g_v(x)+f_u(x)-1gu​(x)=v∈son(u)∑​gv​(x)+fu​(x)−1

所有的生成函数都是 nnn 次的,所以考虑带 n+1n+1n+1 个点值进去算。因为不是 NTT 模数,所以只能带一般的点值最后再插值回来。

这样还是 O(n2w)\Omicron(n^2w)O(n2w) 的。带点值这步不好优化,但后面的枚举值域看起来可以优化一下。

可以动态 dp,但常数巨大,还没暴力跑得快。

注意到不同的阀值的计算过程是一样的,可以考虑用线段树合并维护所有阀值的答案。

开个长度为值域的线段树,我们在线段树的每个叶子记录这个阀值的 (f,g)(f,g)(f,g),初值为 (0,0)(0,0)(0,0)。你需要维护以下操作:

  1. 开头的 fff 区间加和区间乘。
  2. 合并两棵线段树,fff 对应位置相乘, ggg 对应位置相加。
  3. 最后的 f←f+1,g←g+ff\leftarrow f+1,g\leftarrow g+ff←f+1,g←g+f。

手玩一个标记 (a,b,c,d)(a,b,c,d)(a,b,c,d) 表示 (f,g)⟵(af+b,cf+g+d)(f,g)\longleftarrow (af+b,cf+g+d)(f,g)⟵(af+b,cf+g+d),就可以做了。

关于有懒标记的线段树合并:线段树合并的过程中两边有一边没有儿子时直接返回,这样 pushdown 次数和递归次数同阶,不影响复杂度。

最后插值即可。

复杂度 O(wnlog⁡w)\Omicron(wn\log w )O(wnlogw)

#include <iostream>
#include <cstring>
#include <cctype>
#include <cstdio>
#include <vector>
#include <algorithm>
#define MAXN 2005
using namespace std;
inline int read()
{int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans;
}
const int MOD=64123;
typedef long long ll;
inline int add(const int& x,const int& y){return x+y>=MOD? x+y-MOD:x+y;}
inline int dec(const int& x,const int& y){return x<y? x-y+MOD:x-y;}
vector<int> e[MAXN];
inline int qpow(int a,int p)
{int ans=1;while (p){if (p&1) ans=(ll)ans*a%MOD;a=(ll)a*a%MOD,p>>=1;}return ans;
}
struct data
{int a,b,c,d;inline data(const int& a=1,const int& b=0,const int& c=0,const int& d=0):a(a),b(b),c(c),d(d){}
};
inline data operator *(const data& x,const data& y){return data((ll)x.a*y.a%MOD,((ll)y.a*x.b+y.b)%MOD,((ll)x.a*y.c+x.c)%MOD,((ll)x.b*y.c+x.d+y.d)%MOD);}
int n,k,w,val[MAXN];
int ch[MAXN<<5][2],cnt;
data tag[MAXN<<5];
inline void clear()
{for (int i=1;i<=cnt;i++) ch[i][0]=ch[i][1]=0,tag[i]=data();cnt=0;
}
inline void pushtag(int x,const data& v){tag[x]=tag[x]*v;}
inline void pushdown(int x)
{if (!ch[x][0]) ch[x][0]=++cnt;if (!ch[x][1]) ch[x][1]=++cnt;pushtag(ch[x][0],tag[x]),pushtag(ch[x][1],tag[x]);tag[x]=data();
}
int merge(int x,int y)
{if (!x||!y) return x|y;if (!ch[x][0]&&!ch[x][1]) swap(x,y);if (!ch[y][0]&&!ch[y][1]){tag[x]=tag[x]*data(tag[y].b,0,0,0);tag[x]=tag[x]*data(1,0,0,tag[y].d);return x;}pushdown(x),pushdown(y);ch[x][0]=merge(ch[x][0],ch[y][0]);ch[x][1]=merge(ch[x][1],ch[y][1]);return x;
}
void modify(int& x,int l,int r,int ql,int qr,data v)
{if (!x) x=++cnt;if (ql<=l&&r<=qr) return pushtag(x,v);if (qr<l||r<ql) return;int mid=(l+r)>>1;pushdown(x);modify(ch[x][0],l,mid,ql,qr,v),modify(ch[x][1],mid+1,r,ql,qr,v);
}
int querysum(int x,int l,int r)
{if (l==r) return tag[x].d;int mid=(l+r)>>1;pushdown(x);return add(querysum(ch[x][0],l,mid),querysum(ch[x][1],mid+1,r));
}
int rt[MAXN];
void dfs(int u,int f,int v)
{modify(rt[u],1,w,1,w,data(0,1,0,0));modify(rt[u],1,w,1,val[u],data(v,0,0,0));for (int i=0;i<(int)e[u].size();i++)if (e[u][i]!=f){dfs(e[u][i],u,v);rt[u]=merge(rt[u],rt[e[u][i]]);}modify(rt[u],1,w,1,w,data(1,1,1,0));
}
int calc(int v)
{clear();for (int i=1;i<=n;i++) rt[i]=0;dfs(1,0,v);return querysum(rt[1],1,w);
}
int ans[MAXN],s[MAXN],tmp[MAXN],f[MAXN];
int main()
{n=read(),k=read(),w=read();for (int i=1;i<=n;i++) val[i]=read();for (int i=1;i<n;i++){int u,v;u=read(),v=read();e[u].push_back(v),e[v].push_back(u);}for (int v=1;v<=n+1;v++)ans[v]=calc(v);s[0]=1;for (int i=1;i<=n+1;i++){for (int j=i;j>=1;j--)s[j]=dec(s[j-1],(ll)i*s[j]%MOD);      s[0]=(ll)s[0]*(MOD-i)%MOD;}for (int i=1;i<=n+1;i++){int x=ans[i];for (int j=1;j<=n+1;j++) if (i!=j) x=(ll)x*qpow(dec(i,j),MOD-2)%MOD;tmp[0]=(ll)s[0]*qpow(MOD-i,MOD-2)%MOD;for (int j=1;j<=n+1;j++) tmp[j]=(ll)dec(tmp[j-1],s[j])*qpow(i,MOD-2)%MOD;for (int j=0;j<=n+1;j++) f[j]=(f[j]+(ll)x*tmp[j])%MOD;}int res=0;for (int i=k;i<=n;i++) res=add(res,f[i]);cout<<res;return 0;
}

【九省联考2018】秘密袭击【树形dp】【生成函数】【线段树合并】【多项式插值】相关推荐

  1. [BZOJ5250][九省联考2018]秘密袭击(DP)

    5250: [2018多省省队联测]秘密袭击 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 3  Solved: 0 [Submit][Status] ...

  2. P4365 [九省联考2018]秘密袭击coat

    $ \color{#0066ff}{ 题目描述 }$ Access Globe 最近正在玩一款战略游戏.在游戏中,他操控的角色是一名C 国士 兵.他的任务就是服从指挥官的指令参加战斗,并在战斗中取胜. ...

  3. [九省联考2018]秘密袭击coat

    树形dp碾压标算 这道题目我写了60分的暴力(N^2*k),没有优化,只是说一说树形dp相关. 这道题我们可以转化一下,我们可以考虑每一个点对答案的贡献.这道题可以转化为以该点为根的树中包含根的连通块 ...

  4. luogu4365 秘密袭击 (生成函数+线段树合并+拉格朗日插值)

    求所有可能联通块的第k大值的和,考虑枚举这个值: $ans=\sum\limits_{i=1}^{W}{i\sum\limits_{S}{[i是第K大]}}$ 设cnt[i]为连通块中值>=i的 ...

  5. 九省联考2018总结

    前言 我作为一名ZJOI2018day1凉凉选手,为获得更多的省选体验,去上海参加了九省联考2018,当然,是属于外省选手参加的(所以实际并测的时候出现了一些问题也得不到解决),做完两天的题,深有感触 ...

  6. 「Luogu4363/BZOJ5248」[九省联考2018]一双木棋chess

    「Luogu4363/BZOJ5248」[九省联考2018]一双木棋chess 学校省选模拟居然拿九省联考来考 然而我还是\(too\space young\),搞不懂什么叫最优 让二者的答案最接近可 ...

  7. 【洛谷】【博弈搜索】P4363 [九省联考2018]一双木棋chess

    洛谷 P4363 [九省联考2018]一双木棋chess 题目大意 ◇题目传送门◆ 分析 根据题目所给定的规则,可以发现对于每一行,其下面一行上放的棋子数目不可能多于上面的一行. 所以我们可以将每行上 ...

  8. 「九省联考 2018」一双木棋

    「九省联考 2018」一双木棋 题目描述 菲菲和牛牛在一块 \(n\) 行 \(m\) 列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满 ...

  9. LibreOJ #2478.「九省联考 2018」林克卡特树 树形dp+带权二分

    题意 给出一棵n个节点的树和k,边有边权,要求先从树中选k条边,然后把这k条边删掉,再加入k条边权为0的边,满足操作完后的图仍然是一棵树.问新树的带权直径最大是多少. n,k≤3∗105n,k≤3∗1 ...

  10. @loj - 2478@「九省联考 2018」林克卡特树

    目录 @description@ @solution@ @part - 1@ @part - 2@ @accepted code@ @details@ @description@ 小 L 最近沉迷于塞 ...

最新文章

  1. 图形驱动程序和显卡驱动什么区别_我们常说的计算机驱动程序到底是什么,深入解读驱动程序本质...
  2. 【正一专栏】梅西终老巴萨可被裁判吹掉了已进之球
  3. Android开发-下载网络图片并显示到本地
  4. PAT_B_1040_Java(25分)
  5. AA级与AAA级台灯 重要指标对比
  6. 你还不知道Redis 高延迟时发生了啥嘛?
  7. PHP多坐席客服聊天系统源码完美定制版 带原生app+视频教程
  8. vSAN其实很简单-5分钟学会如何向VMware报修故障(内含福利)
  9. JavaScript学习笔记(六)
  10. 黑马程序员-关于C语言基本运算的一些注意点
  11. Avoiding GREEDYDATA for logstash'grok
  12. java pingfang,PingFang sc字体的使用
  13. Ansible的安装和全面介绍
  14. CSS入门到精通——表格样式
  15. Golang方差算法
  16. [情侣空间] 基于spring boot的自制情侣空间
  17. 【EasyRL学习笔记】第九章 Actor-Critic 演员-评论员算法
  18. 199 c 通过函数名字符串调用函数
  19. 3、Maven核心程序解压与配置
  20. Qt+VTK+PCL图片转灰度图且以灰度为Y轴显示

热门文章

  1. 物理学上最厉害的54个男人!2400年来难以超越,没想到聚在一起后这么震撼......
  2. 那些年,画家发明的黑科技
  3. 程序员从入门到升级,或许可以看一看这几个公众号
  4. 全球孩子迷恋手机/iPad,其实罪魁祸首是父母!
  5. 国家特级数学教授李毓佩:我们欠孩子真正的数学阅读 !
  6. java 创建web项目_java – Eclipse:以编程方式创建动态Web项目
  7. java 录屏_java 录屏 小工具源码(idea)
  8. python作业题目用户输入行数、输出倒的等腰三角形_智慧职教云课堂APPPython程序设计(常州工业职业技术学院)作业期末考试答案...
  9. 原型链的理解_javascript之快速理解(原型链)
  10. oracle 监听 无法连接,解决ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务...