【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)
【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)
题面
题解
emmmm,这题似乎猫讲过一次。。。
显然先\(meet-in-the-middle\)搜索一下对于每个有用的苹果数量,满足权值小于\(lim\)的方案数
,那么只需要考虑它们构成生成树的方案数就好了。
显然有用的可以和所有的有用的或者是坏的连边,好的但不有用的只能和坏的连边,而坏的随意。
但是这样子算出来的结果是至多,因此还需要额外容斥一下计算生成树的个数。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 50
#define MOD 1000000007
void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,limit,m,c[MAX];
struct Node{int S,d;}S1[1050000],S2[1050000];
bool operator<(Node a,Node b){return a.S<b.S;}
int top1,top2;
void dfs1(int x,int S,int D)
{
if(S>limit)return;
if(x==m+1){S1[++top1]=(Node){S,D};return;}
dfs1(x+1,S,D);
if(c[x]>-1)dfs1(x+1,S+c[x],D+1);
}
void dfs2(int x,int S,int D)
{
if(S>limit)return;
if(x==n+1){S2[++top2]=(Node){S,D};return;}
dfs2(x+1,S,D);
if(c[x]>-1)dfs2(x+1,S+c[x],D+1);
}
int Cnt[MAX],cc[MAX];
int Sum[MAX],tot;
int a[MAX][MAX],C[MAX][MAX];
int fpow(int a,int b)
{
int s=1;
while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}
return s;
}
void link(int x,int y){++a[x][x],++a[y][y];--a[x][y],--a[y][x];}
int Matrix_Tree(int k)
{
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)a[i][j]=0;
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j)
if(i<=k){if(j<=k||j>tot)link(i,j);}
else if(i>tot)link(i,j);
else if(j>tot)link(i,j);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
a[i][j]=(a[i][j]+MOD)%MOD;
int ans=1;
for(int i=1;i<n;++i)
{
for(int j=i+1;j<n;++j)
{
int t=1ll*a[j][i]*fpow(a[i][i],MOD-2)%MOD;
for(int k=i;k<n;++k)a[j][k]=(a[j][k]+MOD-1ll*t*a[i][k]%MOD)%MOD;
}
ans=1ll*ans*a[i][i]%MOD;
}
return ans;
}
int main()
{
n=read();limit=read();m=(n+1)/2;
for(int i=1;i<=n;++i)c[i]=read();
for(int i=1;i<=n;++i)tot+=(c[i]!=-1);
dfs1(1,0,0);dfs2(m+1,0,0);
sort(&S1[1],&S1[top1+1]);sort(&S2[1],&S2[top2+1]);
for(int i=top1,j=1;i;--i)
{
while(j<=top2&&S1[i].S+S2[j].S<=limit)cc[S2[j].d]+=1,++j;
for(int k=0;k<=n;++k)add(Cnt[S1[i].d+k],cc[k]);
}
for(int i=0;i<=n;++i)C[i][0]=1;
for(int i=1;i<=n;++i)
for(int j=1;j<=i;++j)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
for(int i=0;i<=tot;++i)Sum[i]=Matrix_Tree(i);
for(int i=1;i<=tot;++i)
for(int j=0;j<i;++j)
Sum[i]=(Sum[i]+MOD-1ll*C[i][j]*Sum[j]%MOD)%MOD;
int ans=0;
for(int i=0;i<=tot;++i)add(ans,1ll*Cnt[i]*Sum[i]%MOD);
printf("%d\n",ans);
return 0;
}
【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)的更多相关文章
- loj#6072 苹果树(折半搜索,矩阵树定理,容斥)
loj#6072 苹果树(折半搜索,矩阵树定理,容斥) loj 题解时间 $ n \le 40 $ . 无比精确的数字. 很明显只要一个方案不超过 $ limits $ ,之后的计算就跟选哪个没关系了 ...
- [51Nod1446] 限制价值树 (容斥+MT定理+折半搜索)
传送门 Description 有N个点(N<=40)标记为0,1,2,...N-1,每个点i有个价值val[i],如果val[i]=-1那么这个点被定义为bad,否则如果val[i] > ...
- LOJ #6044 -「雅礼集训 2017 Day8」共(矩阵树定理+手推行列式)
题面传送门 一道代码让你觉得它是道给初学者做的题,然鹅我竟没想到? 首先考虑做一步转化,我们考虑将整棵树按深度奇偶性转化为一张二分图,即将深度为奇数的点视作二分图的左部,深度为偶数的点视作二分图的右部 ...
- [专题总结]矩阵树定理Matrix_Tree及题目&题解
专题做完了还是要说两句留下什么东西的. 矩阵树定理通俗点讲就是: 建立矩阵A[i][j]=edge(i,j),(i!=j).即矩阵这一项的系数是两点间直接相连的边数. 而A[i][i]=deg(i). ...
- 4.9 省选模拟赛 生成树求和 变元矩阵树定理 生成函数 iDFT 插值法
有同学在loj上找到了加强版 所以这道题是可以交的.LINK:生成树求和 加强版 对于30分 爆搜 可实际上我爆搜只过了25分 有同学使用按秩合并并茶几的及时剪枝通过了30分. const int M ...
- loj6271 「长乐集训 2017 Day10」生成树求和 加强版(矩阵树定理,循环卷积)
loj6271 「长乐集训 2017 Day10」生成树求和 加强版(矩阵树定理,循环卷积) loj 题解时间 首先想到先分开三进制下每一位,然后每一位分别求结果为0,1,2的树的个数. 然后考虑矩阵 ...
- [spoj104][Highways] (生成树计数+矩阵树定理+高斯消元)
In some countries building highways takes a lot of time... Maybe that's because there are many possi ...
- BZOJ 4766: 文艺计算姬 [矩阵树定理 快速乘]
传送门 题意: 给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图$K_{n,m}$ 求生成树个数 1 <= n,m,p <= 10^18 显然不能暴力上矩阵树定理 看 ...
- bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥
4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 559 Solved: 325[Submit][Sta ...
随机推荐
- 【转】RCP中org.eclipse.core.runtime.CoreException
org.eclipse.core.runtime.CoreException: Plug-in TRAIN was unable to load class train.Application. 利用 ...
- 【转】redis-cluster安装配置
需要三台虚拟机(生产环境是3个物理机),分配静态IP.cluster中共6个节点.3主3从.本文中每个虚拟机上的redis端口:6379 6380. 需要注意的两点: 3个主节点分别位于3台虚拟机上, ...
- linux系统下MySQL表名区分大小写问题
linux系统下MySQL表名区分大小写问题 https://www.cnblogs.com/jun1019/p/7073227.html [mysqld] lower_case_table_name ...
- # 【Python3练习题 008】判断101-200之间有多少个素数,并输出所有素数。
lst = []for i in range(100): #建立 101-200 的列表 lst.append(101+i) for i in range(101, 201): #除数为 101-20 ...
- spring aop学习记录
许多AOP框架,比较常用的是Spring AOP 与AspectJ.这里主要学习的Spring AOP. 关于AOP 日志.事务.安全验证这些通用的.散步在系统各处的需要在实现业务逻辑时关注的事情称为 ...
- oracle创建视图时一些问题
这几天创建视图的时候,遇见的问题. 一:创建视图的时候Oracle-报错:文字与格式字符串不匹配(ORA-01861) 我创建的时候用的 是to_date 然后我改成了to_char select X ...
- 【学亮IT手记】mysql创建/查看/切换数据库
--创建数据库 create database web_test1 CHARACTER set utf8; --切换数据库 use web_test1; --查看当前使用的数据库 select DAT ...
- django之路由层
一 Django中路由的作用 二 简单的路由配置 三 有名分组 四 路由分发 五 反向解析 六 名称空间 七 django2.0版的path 一 Django中路由的作用 URL配置(URLconf) ...
- Git发生SSL certificate problem: certificate ha错误的解决方法
这两天,不知道为什么,用Git提交代码到服务器时,总出现SSL certificate problem: unable to get local issuer certificate while ac ...
- jdbc工具类2..0
一.创建外部文件 url=jdbc:mysql:///qy66 use=root password=root driver=com.mysql.jdbc.Driver 二.创建工具类 package ...