【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)

题面

LOJ

题解

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;
}

转载于:https://www.cnblogs.com/cjyyb/p/10211311.html

【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)相关推荐

  1. BZOJ1016 || 洛谷P4208 [JSOI2008]最小生成树计数【矩阵树定理】

    时空限制 1000ms / 128MB 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则 ...

  2. 矩阵树定理2020HDU多校第6场j-Expectation[位运算+期望]

    矩阵树定理 用于求解图上面生成树的个数,生成树的个数等于基尔霍夫矩阵的任何一个N-1阶主子式的行列式的绝对值 矩阵树模板 struct Matrix_Tree {ll a[N][N];Matrix_T ...

  3. Luogu P4336 [SHOI2016]黑暗前的幻想乡(容斥,矩阵树定理,子集反演)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Luogu P4336 [SHOI2016]黑暗前的幻想乡(容斥,矩阵树定理) Problem n≤1 ...

  4. 【学习笔记】矩阵树定理(Matrix-Tree)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 一.矩阵树定理 二.常用定理 三.例题 1. Luogu P6178 [模板]Matrix-Tr ...

  5. 图论数学:矩阵树定理

    运用矩阵树定理进行生成树计数 给定一个n个点m条边的无向图,问生成树有多少种可能 直接套用矩阵树定理计算即可 矩阵树定理的描述如下: 首先读入无向图的邻接矩阵,u-v G[u][v]++ G[v][u ...

  6. [CF917D]Stranger Trees[矩阵树定理+解线性方程组]

    题意 给你 \(n\) 个点的无向完全图,指定一棵树 \(S\),问有多少棵生成树和这棵树的公共边数量为 \(k\in[0,n-1]\) \(n\leq 100\) 分析 考虑矩阵树定理,把对应的树边 ...

  7. HDU多校6 - 6836 Expectation(矩阵树定理+高斯消元求行列式)

    题目链接:点击查看 题目大意:给出一张由 n 个点和 m 条边组成的无向图,对于任意一个生成树,其权值为 n - 1 条边的边权进行二进制的 and 运算,现在需要在图中任意选择一个生成树,问期望权值 ...

  8. Wannafly挑战赛23F-计数【原根,矩阵树定理,拉格朗日插值】

    正题 题目链接:https://ac.nowcoder.com/acm/contest/161/F 题目大意 给出nnn个点的一张图,求它的所有生成树中权值和为kkk的倍数的个数.输出答案对ppp取模 ...

  9. P3317-[SDOI2014]重建【矩阵树定理,数学期望】

    正题 题目链接:https://www.luogu.com.cn/problem/P3317 题目大意 nnn个点若干条边.告诉你每条边出现的概率,求刚好出现一颗生成树的概率是多少. 解题思路 矩阵树 ...

最新文章

  1. (转贴)给Repeater、Datalist和Datagrid增加自动编号列
  2. mybatis 使用in 查询时报错_使用mybatis的resultMap进行复杂查询 057
  3. 2018.10.17考试
  4. CIO时代客户交流会,强强联合共筑电子政务美好未来
  5. HIve学习:Hive分区修改
  6. Linux文件查找之findlocate
  7. 22岁少年破解史上最严重网络攻击,拯救全球互联网,三个月后却被FBI逮捕
  8. python程序如何做界面_如何用Python给已有小程序做界面?
  9. Linux开机启动过程(5):内核解压
  10. python unicode转字符串_Python2.X如何将Unicode中文字符串转换成 string字符串
  11. 简单的eda实验vga在linux系统中,《EDA实验报告VGA彩条显示.doc
  12. 转:error LNK2001 错误
  13. Grafana教程(prometheus 基本查询语法,alerting报警)
  14. 我爱刷题系列汇总(51-100)【2017.11.24-2018.01.12】
  15. 面经 | 靠一份PPT做自我介绍,成功拿下了互联网名企offer
  16. AMD GPU 系列版本信息
  17. MIPI 打怪升级之DSI篇
  18. 央行征信与互联网征信技术接口区别(征信架构篇)
  19. 误入 GitHub 游戏区,结果意外地收获颇丰
  20. vsync, hsync, VBLANK

热门文章

  1. SQLServer 修改表字段的长度
  2. 高德地图 2D和3D的区别
  3. Windows10 关键错误,开始菜单cortana无法工作,重启无效
  4. kettle调用oracle存储过程,kettle 调用存储过程
  5. Vue中TipTap富文本编辑器的输入框内部分样式无法显示
  6. GIF 格式解析之表情包是如何动起来的
  7. java三种方法拆分字符串
  8. 如何从充电器取电5V9V12V的方法,XSP06触发QC/PD充电器快充
  9. ZYNQ AXI GPIO中断实验——FPGA Vitis篇
  10. 这篇文章价值很大:股票历史分时成交数据怎么简单获取?【干货】