• LOJ.6160.[美团CodeM初赛 RoundA]二分图染色(容斥 组合)


    题目链接


    (Description)

    求在(2n)个点的完全二分图(两边各有(n)个点)上确定两组匹配,使得两个匹配没有交集的方案数。
    (nleq10^7)

    (Solution)

    不考虑限制,令(f_i)表示在(2i)个点的二分图上任意确定一组匹配的方案数,确定两组匹配的方案数就是(f_n^2)
    对于限制,考虑容斥,枚举令多少个匹配强制相同,即(Ans=sumlimits_{i=0}^n(-1)^ii!(C_n^i)^2f_{n-i}^2)

    对于(f_n),一个显然的求法是(f_n=sum_{i=0}^ni!(C_n^i)^2)。但这样总复杂度就是(O(n^2))了。
    打个表可以找出规律:(f_n=2nf_{n-1}-(n-1)^2f_{n-2})

    理性思考一下(f_n)为什么这么递推,即如何由(n-1)推到(n)。不考虑限制,第(n)对点有(2n-1)种和其它点匹配的方案,再加上不选这对点方案数就是(2nf_{n-1})
    假设第(n)对点中连出的匹配和((i,j))相同,那么有((n-1)^2)种可能,每种可能的方案数都是(f_{n-2})。所以减掉((n-1)^2f_{n-2})


    //3127ms	117372K
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define mod 1000000007
    #define gc() getchar()
    typedef long long LL;
    const int N=1e7+5;
    
    int f[N],fac[N],ifac[N];
    
    inline int read()
    {
    	int now=0,f=1;register char c=gc();
    	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now*f;
    }
    inline int FP(int x,int k)
    {
    	int t=1;
    	for(; k; k>>=1,x=1ll*x*x%mod)
    		if(k&1) t=1ll*t*x%mod;
    	return t;
    }
    
    int main()
    {
    	int n=read(); fac[0]=1;
    	for(int i=1; i<=n; ++i) fac[i]=1ll*fac[i-1]*i%mod;
    	ifac[n]=FP(fac[n],mod-2);
    	for(int i=n; i; --i) ifac[i-1]=1ll*ifac[i]*i%mod;
    	f[0]=1, f[1]=2;
    	for(int i=2; i<=n; ++i) f[i]=(2ll*i*f[i-1]-1ll*(i-1)*(i-1)%mod*f[i-2])%mod;
    
    	LL ans=0,tmp=1ll*fac[n]*fac[n]%mod;
    	#define v (tmp*ifac[n-i]%mod*ifac[n-i]%mod*ifac[i]%mod*f[n-i]%mod*f[n-i]%mod)
    	for(int i=0; i<=n; ++i) ans+=i&1?-v:v;
    	printf("%lld
    ",(ans%mod+mod)%mod);
    
    	return 0;
    }
    
  • 相关阅读:
    表单
    表格
    浮动与定位实例中的问题
    浮动与定位
    BFC的布局规则以及触发条件
    发布为知笔记到博客
    处理为知笔记样式与博客园样式冲突
    文字处理
    块元素并行的问题
    标签嵌套规则
  • 原文地址:https://www.cnblogs.com/SovietPower/p/10639679.html
Copyright © 2020-2023  润新知