• AGC051D C4


    一个无向四元环(顺时针(STUV)),给出每条边经过的次数(a,b,c,d),求从(S)出发,(S)结束的方案数。

    (1le a,b,c,dle 5*10^5)


    以下为了方便,记(F(x,y))表示(x)(y)组合的方案数(即(inom{x+y}{x})),(F(x,y,z))同理。

    普通做法:

    先把不形成欧拉回路的情况判掉。

    把两步连在一起,则可以分为:

    1. S-V-U,U-V-S。
    2. S-T-U,U-T-S。
    3. S-V-S,S-T-S,U-V-U,U-T-U。

    枚举1,2用了多少次,记为(i,j)

    由于来回是对称的,所以1,2直接组合,贡献为(F(i,j))

    考虑S-?-S,它可以是两个1或2组合起来,个数(frac{i+j}{2}),也可以是3中的S-V-S,个数(frac{d-i}{2}),S-T-S,个数(frac{a-j}{2}),贡献为(F(frac{i+j}{2},frac{d-i}{2},frac{a-j}{2}))

    同理,考虑U-?-U,贡献为(F(frac{i+j}{2}-1,frac{c-i}{2},frac{b-j}{2}))

    答案为(sum_{i,j}F(i,j)F(frac{i+j}{2},frac{d-i}{2},frac{a-j}{2})F(frac{i+j}{2}-1,frac{c-i}{2},frac{b-j}{2}))

    可以FFT。

    更简单的做法:

    考虑给边定向。可以发现定向的方案只有(O(n))种,然后套上BEST定理(O(1))计算。

    由于对BEST定理不熟悉搞了好久。

    参考资料:https://oi-wiki.org/graph/matrix-tree/

    (G)有向欧拉图,则欧拉回路(没有固定起点)的总数(ec(G))为:

    [ec(G)=t^{root}(G,k)prod (deg_v-1)! ]

    (t^{root}(G,k))表示(k)为根的根向树计数。它的基尔霍夫矩阵为(D^{out}-E)

    (注意是根向树也叫内向树,而用的度数矩阵为(D^{out})

    由于没有固定起点,于是还需要乘(deg(S)),并且因为不区分同类边,所以要除以各自的阶乘。

    最后还有我看不懂的Tiw-Air-OAO大爷的生成函数做法:https://www.cnblogs.com/Tiw-Air-OAO/p/14440147.html


    using namespace std;
    #include <bits/stdc++.h>
    #define N (1<<21)
    #define mo 998244353
    #define ll long long
    ll qpow(ll x,ll y=mo-2){
    	ll r=1;
    	for (;y;y>>=1,x=x*x%mo)
    		if (y&1)
    			r=r*x%mo;
    	return r;
    }
    int nN,re[N];
    void setlen(int n){
    	int bit=0;
    	for (nN=1;nN<=n;nN<<=1,++bit);
    	for (int i=1;i<nN;++i)
    		re[i]=re[i>>1]>>1|(i&1)<<bit-1;	
    }
    void dft(int A[],int flag){
    	for (int i=0;i<nN;++i)
    		if (i<re[i])
    			swap(A[i],A[re[i]]);
    	static int wnk[N];
    	for (int i=1;i<nN;i<<=1){
    		ll wn=qpow(3,flag==1?(mo-1)/(2*i):mo-1-(mo-1)/(2*i));
    		wnk[0]=1;
    		for (int k=1;k<i;++k)
    			wnk[k]=wnk[k-1]*wn%mo;
    		for (int j=0;j<nN;j+=i<<1)
    			for (int k=0;k<i;++k){
    				ll x=A[j+k],y=(ll)A[j+k+i]*wnk[k];
    				A[j+k]=(x+y)%mo;
    				A[j+k+i]=(x-y)%mo;
    			}
    	}
    	for (int i=0;i<nN;++i)
    		A[i]=(A[i]+mo)%mo;
    	if (flag==-1){
    		ll invn=qpow(nN);
    		for (int i=0;i<nN;++i)
    			A[i]=A[i]*invn%mo;
    	}
    }
    void multi(int c[],int a[],int b[],int n){
    //	for (int i=0;i<=n;++i)
    //		for (int j=0;j<=n;++j)
    //			c[i+j]=(c[i+j]+(ll)a[i]*b[j])%mo;
    	static int A[N],B[N];
    	setlen(n*2);
    	for (int i=0;i<=n;++i)
    		A[i]=a[i],B[i]=b[i];
    	dft(A,1),dft(B,1);
    	for (int i=0;i<nN;++i)
    		A[i]=(ll)A[i]*B[i]%mo;
    	dft(A,-1);
    	for (int i=0;i<=n*2;++i)
    		c[i]=A[i];
    }
    ll fac[N],ifac[N];
    void initC(int n){
    	fac[0]=1;
    	for (int i=1;i<=n;++i)
    		fac[i]=fac[i-1]*i%mo;
    	ifac[n]=qpow(fac[n]);
    	for (int i=n-1;i>=0;--i)
    		ifac[i]=ifac[i+1]*(i+1)%mo;
    }
    ll C(int m,int n){return fac[m]*ifac[n]%mo*ifac[m-n]%mo;}
    int a,b,c,d;
    int f[N],g[N],h[N];
    int main(){
    	freopen("in.txt","r",stdin);
    	scanf("%d%d%d%d",&a,&b,&c,&d);
    	initC(a+b+c+d);
    	if (d+a&1|a+b&1|b+c&1|c+d&1){
    		printf("0
    ");
    		return 0;
    	}
    	for (int i=c&1;i<=c && i<=d;i+=2)
    		f[i]=ifac[i]*ifac[d-i>>1]%mo*ifac[c-i>>1]%mo;
    	for (int j=a&1;j<=a && j<=b;j+=2)
    		g[j]=ifac[j]*ifac[a-j>>1]%mo*ifac[b-j>>1]%mo;
    	int n=max(max(a,b),max(c,d));
    	multi(h,f,g,n);
    	ll ans=0;
    	for (int i=2;i<=n*2;++i)
    		ans=(ans+h[i]*fac[i]%mo*ifac[i/2]%mo*ifac[i/2-1])%mo;
    	ans=ans*fac[d+a>>1]%mo*fac[(b+c>>1)-1]%mo;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    using namespace std;
    #include <bits/stdc++.h>
    #define N (1<<21)
    #define mo 998244353
    #define ll long long
    ll qpow(ll x,ll y=mo-2){
    	ll r=1;
    	for (;y;y>>=1,x=x*x%mo)
    		if (y&1)
    			r=r*x%mo;
    	return r;
    }
    ll fac[N],ifac[N];
    void initC(int n){
    	fac[0]=1;
    	for (int i=1;i<=n;++i)
    		fac[i]=fac[i-1]*i%mo;
    	ifac[n]=qpow(fac[n]);
    	for (int i=n-1;i>=0;--i)
    		ifac[i]=ifac[i+1]*(i+1)%mo;
    }
    ll C(int m,int n){return fac[m]*ifac[n]%mo*ifac[m-n]%mo;}
    int a,b,c,d;
    int pa,pb,pc,pd;
    ll calc(ll _11,ll _12,ll _13,ll _21,ll _22,ll _23,ll _31,ll _32,ll _33){
    	ll s=0;
    	s+=_11*_22*_33;
    	s+=_11*_23*_32*(-1);
    	s+=_12*_21*_33*(-1);
    	s+=_12*_23*_31;
    	s+=_13*_21*_32;
    	s+=_13*_22*_31*(-1);
    	return s%mo;
    }
    int main(){
    	freopen("in.txt","r",stdin);
    	scanf("%d%d%d%d",&a,&b,&c,&d);
    	initC(a+b+c+d);
    	if (d+a&1|a+b&1|b+c&1|c+d&1){
    		printf("0
    ");
    		return 0;
    	}
    	ll ans=0;
    	for (pa=0;pa<=a;++pa){
    		pb=2*pa-a+b>>1;
    		pc=2*pb-b+c>>1;
    		pd=2*pc-c+d>>1;
    		if (pb<0 || pc<0 || pd<0 || pb>b || pc>c || pd>d)
    			continue;
    		ll tmp=(pa+d-pd)*ifac[pa]%mo*ifac[a-pa]%mo*ifac[pb]%mo*ifac[b-pb]%mo*ifac[pc]%mo*ifac[c-pc]%mo*ifac[pd]%mo*ifac[d-pd]%mo;
    		tmp=tmp*fac[pa+d-pd-1]%mo*fac[pb+a-pa-1]%mo*fac[pc+b-pb-1]%mo*fac[pd+c-pc-1]%mo;
    		tmp=tmp*calc(pb+a-pa,-pb,0,-(b-pb),pc+b-pb,-pc,0,-(c-pc),pd+c-pc)%mo;
    		(ans+=tmp)%=mo;
    	}
    	ans=(ans+mo)%mo;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    【转】Spring高级进阶:BeanFactoryPostProcessor
    【转】2019版本idea导入新spring boot项目有关配置讲解及右侧没有maven解决方式
    jquery 选择器(name,属性,元素)大全
    【转】读懂正则表达式就这么简单
    【转】跨站脚本攻击(XSS)
    Oracle 分页查询 插叙不出数据
    spring:过滤器和拦截器
    Idea-每次修改JS文件都需要重启Idea才能生效解决方法 热部署
    IDEA: Call Hierarchy
    Linux之文件读取查看之cat、head、tail、tac、rev、more、less
  • 原文地址:https://www.cnblogs.com/jz-597/p/14515942.html
Copyright © 2020-2023  润新知