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

LOJ6072苹果树的更多相关文章

  1. codevs 1228 苹果树 树链剖分讲解

    题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上 ...

  2. AC日记——苹果树 codevs 1228

    1228 苹果树  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 在卡卡的房子外面,有一棵 ...

  3. BZOJ 3757: 苹果树

    3757: 苹果树 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1726  Solved: 550[Submit][Status][Discuss] ...

  4. codevs1228 苹果树

    题目描述 Description 在卡卡的房子外面,有一棵苹果树.每年的春天,树上总会结出很多的苹果.卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树.我们知道树是有很多分叉点的,苹果会长在枝条的 ...

  5. 【BZOJ-3757】苹果树 块状树 + 树上莫队

    3757: 苹果树 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1305  Solved: 503[Submit][Status][Discuss] ...

  6. 洛谷P2015 二叉苹果树

    题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来 ...

  7. 【BZOJ】【3757】苹果树

    树分块 orz HZWER http://hzwer.com/5259.html 不知为何我原本写的倍增求LCA给WA了……学习了HZWER的倍增新姿势- 树上分块的转移看vfk博客的讲解吧……(其实 ...

  8. CJOJ 1976 二叉苹果树 / URAL 1018 Binary Apple Tree(树型动态规划)

    CJOJ 1976 二叉苹果树 / URAL 1018 Binary Apple Tree(树型动态规划) Description 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的 ...

  9. 【洛谷2015】【CJOJ1976】二叉苹果树

    题面 Description 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1.我们用一根树枝两端连 ...

随机推荐

  1. tp框架中的一些疑点知识-7

    mysqli是用面向对象的,所以用箭头对象语法, 而mysql是用C语言面向过程写的, 所以用的都是php全局函数 式的写法. tinkle: 叮叮当当的响; (口语)一次电话, i will giv ...

  2. 比较好的一些 ConcurrentHashMap讲解博客

    jdk8 https://blog.csdn.net/jianghuxiaojin/article/details/52006118#commentBox jdk7.8 https://crossov ...

  3. 关于COM类工厂80070005和8000401a错误分析及解决办法

    关于COM类工厂80070005和8000401a错误分析及解决办法 看到很多相关的文章,第一次配置配置时没有啥作用,让别人来解决的,可惜不晓得他怎么解决的,当我再次遇到时,不得不硬着头皮去解决. 总 ...

  4. 关于C#引用ExceptionPolicy.HandleException(ex, "LogAndReplace", out exceptionToReplace);

    http://www.cnblogs.com/Terrylee/archive/2006/07/03/enterprise_library2_1.html 要使用ExceptionPolicy.Han ...

  5. IE8下面parseInt('08')、parseInt('09')会转成0

    例子: <html> <body> <script type="text/javascript"> for(var i=1;i<=20;i ...

  6. (转载)c# winform 窗体起始位置 设置

    窗体起始位置为顶部中间,WinForm居中显示: ; ; this.StartPosition = FormStartPosition.Manual; //窗体的位置由Location属性决定 thi ...

  7. (转载)C#控件缩写规范

    标准控件缩写规范 类 型 前 缀 示 例 Adrotator adrt adrtTopAd BulletedList blst blstCity Button btn btnSubmit Calend ...

  8. 5、lvs使用进阶(01)

    四层.七层负载均衡的区别  https://jaminzhang.github.io/lb/L4-L7-Load-Balancer-Difference/   netfilter/iptables简介 ...

  9. SQLServer代理新建或者编辑作业报错

    SQLServer代理新建或者编辑作业的时候报错如下 错误信息: 标题: Microsoft SQL Server Management Studio------------------------- ...

  10. JAVA之经典算法

    package Set.Java.algorithm; import java.util.Scanner; public class algorithm { /** * [程序1] 题目:古典问题:有 ...