• LOJ6072 「2017 山东一轮集训 Day5」苹果树


    Link
    先计算出有多少个大小为(i)的苹果集合满足其权值和不大于(lim)
    这可以通过双搜在(O(n2^{frac n2}))的时间复杂度内完成。
    那么现在我们就只需要考虑对每个(i)求出使得树上恰好有(i)个有用苹果的方案数(f_i)
    考虑先用Kirchhoff定理求出(g_i)表示至多有(i)个有用的苹果的方案数。
    具体而言我们令钦定(i)个有用点,它们能和其它的有用点以及坏点连边,好但没用点只能和坏点连边,坏点可以和所有点连边。然后计算其生成树个数。
    然后利用容斥可以得出(f_i=sumlimits_{j=i}^n{n-ichoose j-i}f_j)。(这里的(n)指好苹果的个数)

    #include<cstdio>
    #include<cstring>
    #include<utility>
    #include<algorithm>
    #include<functional>
    using pi=std::pair<int,int>;
    const int N=47,M=1<<20|1,P=1000000007;
    int n,x,lim,c1,c2,val[N],C[N][N],f[N],a[N][N],t[N];pi t1[M],t2[M];
    int read(){int x;scanf("%d",&x);return x;}
    void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
    void dec(int&a,int b){a-=b,a+=a>>31&P;}
    int mul(int a,int b){return 1ll*a*b%P;}
    int pow(int a,int b){int r=1;for(;b;b>>=1,a=mul(a,a))if(b&1)r=mul(a,r);return r;}
    void add(int u,int v){dec(a[u][v],1),dec(a[v][u],1),inc(a[u][u],1),inc(a[v][v],1);}
    int det()
    {
        int r=1;
        for(int i=1;i<n;r=mul(r,a[i][i]),++i)
        {
            for(int j=i+1;j<n;++j)
    	{
    	    if(!a[j][i]) continue;
    	    for(int k=i,x=mul(a[i][i],pow(a[j][i],P-2));k<=n;++k) dec(a[i][k],mul(x,a[j][k]));
    	    for(int k=(r=P-r,i);k<=n;++k) std::swap(a[i][k],a[j][k]);
            }
    	if(!a[i][i]) return 0;
        }
        return r;
    }
    int calc(int y)
    {
        memset(a,0,sizeof a);
        for(int i=1;i<=y;++i) for(int j=x+1;j<=n;++j) add(i,j);
        for(int i=y+1;i<=n;++i) for(int j=i+1;j<=n;++j) add(i,j);
        return det();
    }
    void dfs(int now,int sum,int num,int f)
    {
        if(sum>lim) return ;
        if(!f&&now==x/2+1) return t1[++c1]={num,sum},void();
        if(f&&now==x+1) return t2[++c2]={num,sum},void();
        dfs(now+1,sum,num,f),dfs(now+1,sum+val[now],num+1,f);
    }
    int main()
    {
        n=read(),lim=read();int ans=0;
        for(int i=1;i<=n;++i) val[i]=read();
        std::sort(val+1,val+n+1,std::greater<int>()),x=std::lower_bound(val+1,val+n+1,-1,std::greater<int>())-val-1;
        for(int i=0;i<=x;++i) for(int j=C[i][0]=1;j<=i;++j) inc(C[i][j]=C[i-1][j-1],C[i-1][j]);
        for(int i=0;i<=x;++i) f[i]=calc(i);
        for(int i=x;~i;--i) for(int j=i+1;j<=x;++j) dec(f[i],mul(C[x-i][j-i],f[j]));
        std::reverse(f,f+x+1),dfs(1,0,0,0),dfs(x/2+1,0,0,1);
        std::sort(t1+1,t1+c1+1,[](const pi&a,const pi&b){return a.second<b.second;});
        std::sort(t2+1,t2+c2+1,[](const pi&a,const pi&b){return a.second<b.second;});
        for(int i=1;i<=c2;++i) ++t[t2[i].first];
        for(int i=1,j=c2;i<=c1;++i)
        {
    	while(j&&t1[i].second+t2[j].second>lim) --t[t2[j--].first];
    	for(int k=0;k<=n-x/2;++k) inc(ans,mul(f[t1[i].first+k],t[k]));
        }
        printf("%d",ans);
    }
    
  • 相关阅读:
    中小企业服务器配置方案(第三章 Web服务器)
    判断中日韩文的正则表达式
    中小企业服务器配置方案(第一章 代理接入服务器)
    ThinkPHP怎么样更好的使用Smarty第三方插件
    thinkphp 的目录结构
    学习Mysql命令行
    中小企业服务器配置方案(第五章 文件服务器)
    正则字符对应说明
    mysql导入导出.sql文件备份还原数据库[mysql导入导出sql命令行]
    中小企业服务器配置方案(第四章 邮件服务器)
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12825228.html
Copyright © 2020-2023  润新知