loj#6072 苹果树(折半搜索,矩阵树定理,容斥)
loj#6072 苹果树(折半搜索,矩阵树定理,容斥)
题解时间
$ n \le 40 $ 。
无比精确的数字。
很明显只要一个方案不超过 $ limits $ ,之后的计算就跟选哪个没关系了。
折半搜索排序来统计有i个果子是有用的情况下的方案数。
然后矩阵树求生成树个数,容斥乱搞。
#include<bits/stdc++.h>
using namespace std;
template<typename TP>inline void read(TP &tar)
{
	TP ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){ret=ret*10+(ch-'0');ch=getchar();}
	tar=ret*f;
}
namespace RKK
{
const int N=50,mo=1000000007;
void doadd(int &a,int b){if((a+=b)>=mo)a-=mo;}
int add(int a,int b){return (a+=b)>=mo?a-mo:a;}
int fpow(int a,int p){int ret=1;while(p){if(p&1)ret=1ll*ret*a%mo;a=1ll*a*a%mo,p>>=1;}return ret;}
struct pat{int x,y;bool operator < (const pat &p)const{return x<p.x;}};
int n,halfn,lim,val[N],msn;
pat l1[1145141];int tp1;
pat l2[1145141];int tp2;
void dfs1(int x=1,int sum=0,int cnt=0)
{
	if(sum>lim) return;if(x>halfn){l1[++tp1]=(pat){sum,cnt};return;}
	dfs1(x+1,sum,cnt);if(~val[x]) dfs1(x+1,sum+val[x],cnt+1);
}
void dfs2(int x=halfn+1,int sum=0,int cnt=0)
{
	if(sum>lim) return;if(x>n){l2[++tp2]=(pat){sum,cnt};return;}
	dfs2(x+1,sum,cnt);if(~val[x]) dfs2(x+1,sum+val[x],cnt+1);
}
int c[N][N];void init(){for(int i=0;i<=40;i++){c[i][0]=1;for(int j=1;j<=i;j++)c[i][j]=add(c[i-1][j-1],c[i-1][j]);}}
int ma[N][N];
int calc(int sn)
{
	memset(ma,0,sizeof(ma));
	for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++)
	{
		if((i<=sn&&(j<=sn||j>msn))||i>msn||j>msn)
			ma[i][i]++,ma[j][j]++,doadd(ma[i][j],mo-1),doadd(ma[j][i],mo-1);
	}
	int b=n-1;int f=1;
	for(int l=1;l<=b;l++)
	{
		int g=l;for(;g<=b&&!ma[g][l];g++);if(g>b) return 0;
		if(g!=l){for(int j=l;j<=b;j++) swap(ma[l][j],ma[g][j]);f=-f;}
		for(g=l+1;g<=b;g++)
		{
			int k=1ll*ma[g][l]*fpow(ma[l][l],mo-2)%mo;
			for(int j=l;j<=b;j++) doadd(ma[g][j],mo-1ll*ma[l][j]*k%mo);
		}
	}
	if(f==-1) f=mo-1;
	for(int i=1;i<=b;i++) f=1ll*f*ma[i][i]%mo;
	return f;
}
int cnt[N],sum[N];
int cnttmp[N];
int main()
{
	read(n),read(lim),halfn=n+1>>1;
	for(int i=1;i<=n;i++) read(val[i]),msn+=(val[i]!=-1);
	dfs1(),dfs2();init();
	sort(l1+1,l1+tp1+1),sort(l2+1,l2+tp2+1);
	for(int i1=tp1,i2=1;i1;i1--)
	{
		for(;i2<=tp2&&l1[i1].x+l2[i2].x<=lim;cnttmp[l2[i2].y]++,i2++);
		for(int j=0;j<=n;j++) doadd(cnt[l1[i1].y+j],cnttmp[j]);
	}
	for(int i=0;i<=msn;i++) sum[i]=calc(i);
	for(int i=1;i<=msn;i++)for(int j=0;j<i;j++)
		doadd(sum[i],mo-1ll*c[i][j]*sum[j]%mo);
	int ans=0;
	for(int i=0;i<=msn;i++) doadd(ans,1ll*cnt[i]*sum[i]%mo);
    printf("%d\n",ans);
	return 0;
}
}
int main(){return RKK::main();}
loj#6072 苹果树(折半搜索,矩阵树定理,容斥)的更多相关文章
- bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥
		4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 559 Solved: 325[Submit][Sta ... 
- 【bzoj4596】[Shoi2016]黑暗前的幻想乡 (矩阵树定理+容斥)
		Description 四年一度的幻想乡大选开始了,最近幻想乡最大的问题是很多来历不明的妖怪涌入了幻想乡,扰乱了幻想乡昔日的秩序.但是幻想乡的建制派妖怪(人类)博丽灵梦和八云紫等人整日高谈所有妖怪平等 ... 
- [SHOI2016] 黑暗前的幻想乡 - 矩阵树定理,容斥
		#include <bits/stdc++.h> using namespace std; #define int long long const int N = 20; const in ... 
- 洛谷 P4336 黑暗前的幻想乡 —— 容斥+矩阵树定理
		题目:https://www.luogu.org/problemnew/show/P4336 当作考试题了,然而没想出来,呵呵. 其实不是二分图完美匹配方案数,而是矩阵树定理+容斥... 就是先放上所 ... 
- 【LOJ#6072】苹果树(矩阵树定理,折半搜索,容斥)
		[LOJ#6072]苹果树(矩阵树定理,折半搜索,容斥) 题面 LOJ 题解 emmmm,这题似乎猫讲过一次... 显然先\(meet-in-the-middle\)搜索一下对于每个有用的苹果数量,满 ... 
- 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的树的个数. 然后考虑矩阵 ... 
随机推荐
- Solution -「Code+#4」「洛谷 P4370」组合数问题 2
			\(\mathcal{Description}\) Link. 给定 \(n,k\),求 \(0\le b\le a\le n\) 的 \(\binom{a}{b}\) 的前 \(k\) 大. ... 
- 使用SetTrustedCredmanAccessPrivilege获取已保存的凭据
			windows系统中有一个名为SeTrustedCredmanAccessPrivilege的权限,使拥有该特权的进程可作为受信任的调用者访问凭据管理器. 凭据管理器可以从控制面板 -> ... 
- 看我如何使用 shell 来获取所有 KVM 虚拟机的 IP 地址
			文章目录 脚本说明 脚本展示 效果展示 此脚本的初衷是因为,KVM创建的桥接网卡的虚拟机,无法使用virsh domifaddr命令获取IP,而创建的nat网卡的虚拟机,则可以直接使用virsh do ... 
- c++ 字符串替换程序 p324
			字符串替换程序 C++ Primer 324页 // replace:从str字符串中查找oldVal字符串,如果找到就替换成newVal字符串. void replace(string &s ... 
- 树莓派GPIO开发(三):蜂鸣器-PWM调节
			配置环境 系统:Raspbian11(官方64位) 设备:树莓派CM4 一.写在前面 关于PWM的基本介绍在上一篇博客已经说过了:树莓派GPIO开发(二)RGB模块-PWM调节 在RGB模块中,我们主 ... 
- OLAP阵营又增一猛将,比肩Power BI不是说说而已!
			说到大数据应用最多的技术,不得不提OLAP技术,在国内外,不论传统公司还是互联网公司,都开始利用OLAP技术分析挖掘大数据的价值.也许很多人对OLAP的概念还不是很清楚,简单来说,就把数据处理成数据立 ... 
- WPF中ComboBox控件的SelectedItem和SelectedValue的MVVM绑定
			问题描述:左侧是一个ListView控件,用于显示User类的Name属性,右侧显示其SelectedItem的其他属性,包括Age, Address,和Category.其中Category用Com ... 
- svn问题总结
			有问题先尝试右键刷新,或clean up svn图标不显示 解决办法:打开注册表regedit,HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Curren ... 
- MySQL-DB-封装-入门版
			<?php class MysqlDb{ public $host = "127.0.0.1"; public $user = "root"; publi ... 
- php 23种设计模型 - 中介者模式
			中介者模式 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性.这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护.中介者模式属于行 ... 
