zoukankan      html  css  js  c++  java
  • SweetFruits TopCoder

    SweetFruits TopCoder - 12141(Matrix-Tree)

    问题看起来很复杂,不可写,所以先考虑分解一下

    假设最后生效的点集为(V),那么答案只和(sum sweetness[V_i])(|V|)有关

    所以可以考虑对于每一种(|V|),先预处理出方案数

    得知每一种(|V|)的方案数之后,可以用( ext{meet in the middle})法枚举得到(sum sweetness[V_i]leq maxsweetness)的方案数

    方案数是有限制的生成树个数,所以考虑用( ext{Matrix-Tree})

    限定有(a)个点生效,(b)个点不生效,(c)个点是(-1)

    那么可能出现的边是(a-a,a-c,b-c)三种

    但是我们无法保证(a)中的点一定生效,所以可以用容斥/二项式反演得到

    #include<bits/stdc++.h>
    using namespace std;
    
    #define Mod1(x) ((x>=P)&&(x-=P))
    #define Mod2(x) ((x<0)&&(x+=P))
    
    #define reg register
    typedef long long ll;
    #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
    
    #define pb push_back
    template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
    template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
    
    char IO;
    int rd(){
    	int s=0;
    	int f=0;
    	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const int N=50,P=1e9+7;
    
    ll qpow(ll x,ll k=P-2) {
    	ll res=1;
    	for(;k;k>>=1,x=x*x%P) if(k&1) res=res*x%P;
    	return res;
    }
    
    int n,m;
    
    struct Mat{
    	int a[N][N];
    	Mat(){ memset(a,0,sizeof a); }
    	int Det(int n){  // 用于Matrix-Tree的
    		static int G[N][N];
    		rep(i,1,n) rep(j,1,n) G[i][j]=a[i][j];
    		int res=1;
    		rep(i,1,n) {
    			if(!G[i][i]) rep(j,i+1,n) if(G[j][i]){ res=P-res; swap(G[i],G[j]); break; }
    			if(!G[i][i]) continue;
    			ll Inv=qpow(a[i][i]);
    			rep(j,i+1,n) {
    				ll t=a[j][i]*Inv%P;
    				rep(k,i,n) a[j][k]=(a[j][k]-1ll*a[i][k]*t%P+P)%P;
    			}
    		}
    		rep(i,1,n) res=1ll*res*a[i][i]%P;
    		return res;
    	}
    };
    
    int w[N],G[N][N],C[N][N];
    void Init(){
    	rep(i,0,N-1) rep(j,C[i][0]=1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
    	rep(i,0,n) {
    		Mat T;
    		rep(j,1,m) { // -1
    			rep(k,1,n+m) T.a[j][k]=-1;
    			T.a[j][j]=n+m-1;
    		}
    		rep(j,m+1,m+i) { // 生效
    			rep(k,1,m+i) if(j!=k) T.a[j][k]=-1;
    			T.a[j][j]=m+i-1;
    		}
    		rep(j,m+i+1,m+n) { // 不生效
    			rep(k,1,m) T.a[j][k]=-1;
    			T.a[j][j]=m;
    		}
    		w[i]=T.Det(n+m-1);
    	}
    	rep(i,0,n) rep(j,0,i-1) w[i]=(w[i]-1ll*C[i][j]*w[j]%P+P)%P; // 容斥/二项式反演
    }
    
    int val[N];
    vector <int> st[N/2];
    
    
    int Meet_In_The_Middle(int Max){
    	int ans=0,mid=n/2;
    	rep(i,0,mid) st[i].clear();
    	rep(S,0,(1<<mid)-1) {
    		int c=0,s=0;
    		rep(i,0,mid-1) if(S&(1<<i)) s+=val[i],c++;
    		if(s<=Max) st[c].pb(s);
    	}
    	rep(i,0,mid) sort(st[i].begin(),st[i].end());
    	rep(S,0,(1<<(n-mid))-1) {
    		int c=0,s=0;
    		rep(i,0,n-mid-1) if(S&(1<<i)) s+=val[i+mid],c++;
    		if(s>Max) continue;
    		rep(j,0,mid) {
    			int x=upper_bound(st[j].begin(),st[j].end(),Max-s)-st[j].begin();
    			if(x) ans=(ans+1ll*x*w[c+j])%P;
    		}
    	}
    	return ans;
    }
    
    class SweetFruits {
    public:
    	int countTrees(vector <int> Val, int Max) {
    		sort(Val.begin(),Val.end(),greater <int> ());
    		m=0; while(Val.size() && *Val.rbegin()==-1) m++,Val.pop_back();
    		n=Val.size();
    		rep(i,0,n-1) val[i]=Val[i];
    		Init();
    		return Meet_In_The_Middle(Max);
    	}
    };
    
    
    
  • 相关阅读:
    第五周课后作业
    第五周读书笔记
    PB16120853+JL17110067
    第一次个人作业报告
    《编程匠艺》读书笔记----第四周
    软工第一次个人作业博客(一)
    软工第一次个人作业博客(二)
    《程序员修炼之道》读书笔记(二)--第三周
    关于在aspx前台使用后台变量的问题
    sql语句优化SQL Server
  • 原文地址:https://www.cnblogs.com/chasedeath/p/13044254.html
Copyright © 2011-2022 走看看