LOJ6072苹果树
https://loj.ac/problem/6072
虽然结合了很多算法,但是一步一步地推一下还不算太难的一道题。
首先考虑枚举枚举有用的苹果的集合,然后去算生成树个数。
先考虑怎么计算生成树个数。
发现可以使用matrix-tree。
所有有用点可以和有用点以及坏点连边,所有不是坏点的无用点只能和坏点连边,坏点可以和所有点连边。
然后跑一下matrix-tree。但是这样算出来的是至多S这个集合为有用点的方案数,需要套一个容斥。
分析上述过程,发现需要的信息只有好点的个数。
因此可以只需要计算出大小为k的和<lim合法集合有多少即可,这个显然可以meet in the middle。
#include<bits/stdc++.h>
#define N 44
#define M 1100000
#define ll long long
using namespace std;
inline int read()
{char ch=0;int x=0,flag=1;while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return x*flag;
}
const int mo=1e9+7;
int ksm(int x,int k)
{int ans=1;while(k){if(k&1)ans=1ll*ans*x%mo;k>>=1;x=1ll*x*x%mo;}return ans;
}
int inv(int x){return ksm((x%mo+mo)%mo,mo-2);}
int a[N][N];
int matrix_tree(int n)
{int ans=1;for(int i=1;i<=n;i++)if(!a[i][i])return 0;for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){int t=1ll*a[j][i]*inv(a[i][i])%mo;for(int k=i;k<=n;k++)a[j][k]=(a[j][k]-(1ll*t*a[i][k]%mo))%mo;}ans=1ll*ans*a[i][i]%mo;}return (ans%mo+mo)%mo;
}
int w[N],sz[N],dp[N],ans[N],c[N][N],f[N/2][M];
bool cmp(int a,int b){return a>b;}
int main()
{int n=read(),lim=read(),cnt=0,res=0;for(int i=1;i<=n;i++)w[i]=read(),cnt+=(w[i]==-1);sort(w+1,w+n+1,cmp);int m=n-cnt,mid=m/2;for(int s=0;s<(1<<mid);s++){int num=0,tot=0;for(int i=1;i<=mid;i++)if(1<<(i-1)&s)num++,tot+=w[i];if(tot<=lim)f[num][++sz[num]]=tot;}for(int i=0;i<=mid;i++)sort(f[i]+1,f[i]+sz[i]+1);for(int s=0;s<(1<<(m-mid));s++){int num=0,tot=0;for(int i=1;i<=m-mid;i++)if(1<<(i-1)&s)num++,tot+=w[i+mid];for(int i=0;i<=mid;i++)dp[i+num]=(dp[i+num]+(upper_bound(f[i]+1,f[i]+sz[i]+1,lim-tot)-f[i]-1))%mo;}for(int i=0;i<=n;i++){c[i][0]=1;for(int j=1;j<=n;j++)c[i][j]=(c[i-1][j-1]+c[i-1][j])%mo;}for(int o=0;o<=m;o++){for(int i=1;i<=o;i++)for(int j=1;j<=n;j++)if(i==j)a[i][j]=(o-1)+cnt;else a[i][j]=-(j<=o||j>m);for(int i=o+1;i<=m;i++)for(int j=1;j<=n;j++)if(i==j)a[i][j]=cnt;else a[i][j]=-(j>m);for(int i=m+1;i<=n;i++)for(int j=1;j<=n;j++)if(i==j)a[i][j]=n-1;else a[i][j]=-1;ans[o]=matrix_tree(n-1);for(int i=0;i<o;i++)ans[o]=(ans[o]-(1ll*c[o][i]*ans[i]%mo))%mo;res=(res+(1ll*dp[o]*ans[o]%mo))%mo;}printf("%d",(res%mo+mo)%mo);return 0;
}
转载于:https://www.cnblogs.com/Creed-qwq/p/10641579.html
LOJ6072苹果树相关推荐
- 【LOJ6072】苹果树【折半搜索】【矩阵树定理】【二项式反演】
题意:有好坏两种点共 nnn 个,每个好点有权值,把这 nnn 个点连成一棵树,一个好点为有用的当且仅当它至少与一个好点相邻,求所有有用的点的权值和不超过 limlimlim 的方案数. n≤40n\ ...
- P2015 二叉苹果树
传送门 这道题要用到链式前向星... 非常标准的树形背包DP 只要理解了,题就不难 只要理解了...... 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树 ...
- 苹果树的故事(转发的)
一棵苹果树,终于结果了. 第一年,它结了十个苹果,九个被拿走,自己得到一个.对此,苹果树愤愤不平,于是自断经脉,拒绝成长.第二年,它结了五个苹果,四个被拿走,自己得到一个."哈哈,去年我得到 ...
- 洛谷 P2015 二叉苹果树
题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来 ...
- 二叉苹果树(树型DP+背包)
二叉苹果树 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点).这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号 ...
- JZOJ 1016. 【PKU3321】苹果树
Description 你家门前种了一棵苹果树,每年秋天,树上都结满了苹果,你非常喜欢吃苹果,所以一直精心照料着苹果树. 苹果树有N个分叉,分叉之间由枝干相连,你把分叉用1到N来标记,树根必须记为1. ...
- 洛谷2015 二叉苹果树 树形DP
https://www.luogu.org/problemnew/show/P2015 二叉苹果树 时间限制: 1 Sec 内存限制: 128 MB 题目描述 有一棵苹果树,如果树枝有分叉,一定是分 ...
- 苹果树(线段树+Dfs序)
1228 苹果树 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 在卡卡的房子外面,有一棵苹果树.每年的春天,树上总会结 ...
- 兰州大学第一届 飞马杯 ★★快乐苹果树★★ 树链剖分 + 懒标记 + 树状数组
传送门 文章目录 题意: 思路: 题意: 思路: 第一次听说树链剖分能在fa[top[i]]fa[top[i]]fa[top[i]]的地方加懒标记,学到了学到了. 首先不能被题目吓住,这个题目仔细剖析 ...
最新文章
- php imagecopy 用法,php使用imagecopymerge()函数创建半透明水印
- 001_Gson概述
- ArcObjects中的几何对象简介(一)
- 递归行为时间复杂度估算
- 【云上ELK系列】Logstash迁移Elasticsearch数据方法解读
- 一篇讲清:如何构建可重复,可扩展且盈利的“魔力”转化流程?
- 了解jQuery并掌握jQuery对象和DOM对象的区别
- linux内核的冒险md来源释义# 14raid5非条块读
- python怎么绘制渐变图_用Python画colorbar渐变图+修改刻度大小+修改渐变颜色
- 我国四大常用坐标系及高程坐标系【转载】
- 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字(简单易懂)
- step14. ubuntu18.04下载安装scala(转)
- 在CentOS 7 1804 中 安装 使用 GitLab 11.4.3-ee (企业版、社区版最新版、或任意版本)
- 同花顺显示正在切换服务器,同花顺服务器架构
- ros平台下python脚本控制机械臂运动
- 服务器系统盘如何克隆,如果把云服务器系统盘克隆
- CAD关闭图层快捷键,隐藏显示的CAD图层
- 弯下腰,只为一个昂起头的机会
- A Survey of Recent Development in Indoor Visible Light Positioning
- udo/tcp协议占用端口列表(因5060被占用而采用的新端口)