AGC 051 D C4 题解

Posted Gary2005

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AGC 051 D C4 题解相关的知识,希望对你有一定的参考价值。

AGC 051 D C4 题解

首先这个图是一个二分图,可以将路径看成一个一个首尾相连的来回。

有以下几种来回:

  1. 从一个点出发回到自己(4种),数量记为\\(a,b,c,d\\)
  2. 从一个点出发到达另一个点,数量记为\\(e,f\\)

如果直接解方程的话,就会有\\(2\\)个自由元,不妨令其为\\(e,f\\)

不过把式子列出来,\\(a,b,c,d,e,f\\)的贡献只和\\(e,f,e+f\\)有关,所以可以用fft优化。

时间复杂度为\\(O(N\\log N)\\)

code:

(namespace 里的部分可以看我以前的博客)

using namespace mypoly;
const int MAXN=1e6+5;
vector<int> f1,f2;
int fact[MAXN<<1],ifact[MAXN<<1];
int comb(int A,int B){
	return 1ll*fact[A]*ifact[B]%MOD*ifact[A-B]%MOD; 
}
int main(){
	fact[0]=1;
	rb(i,1,2000000) fact[i]=1ll*fact[i-1]*i%MOD;
	ifact[2000000]=inv(fact[2000000]);
	rl(i,2000000-1,0) ifact[i]=1ll*(i+1)*ifact[i+1]%MOD;
	int b,d,c,a;
	cin>>b>>d>>c>>a;
	f1.resize(min(a,c)+1);
	f2.resize(min(b,d)+1);
	if((a&1)==(b&1)&&(a&1)==(c&1)&&(a&1)==(d&1));
	else{
		puts("0");
		return 0;
	}
	rb(e,0,min(a,c)){
		if((e&1)==(a&1)){
			f1[e]=1ll*ifact[e]*ifact[(a-e)>>1]%MOD*ifact[(c-e)>>1]%MOD;
		}
	}
	rb(f,0,min(b,d)){
		if((f&1)==(b&1)){
			f2[f]=1ll*ifact[f]*ifact[(b-f)>>1]%MOD*ifact[(d-f)>>1]%MOD;
		}
	}
	f1=f2*f1;
	int rest=0;
	rep(i,f1.size()){
		if(i&1) continue;
		int val=f1[i];
		val=1ll*val*fact[i]%MOD;
		val=1ll*val*fact[(a+b-i)>>1]%MOD;
		val=1ll*val*fact[(c+d-i)>>1]%MOD;
		int t=i/2+1,r=i/2;
		int A=(a+b-i)/2;
		int B=(c+d-i)/2;
		val=1ll*val*comb(A+t-1,t-1)%MOD;
		val=1ll*val*comb(B+r-1,r-1)%MOD;
		(rest+=val)%=MOD;
	}
	printf("%d\\n",rest);
	return 0;
}

以上是关于AGC 051 D C4 题解的主要内容,如果未能解决你的问题,请参考以下文章

AGC025简要题解

题解-Atcoder_agc005D ~K Perm Counting

AGC002 简要题解

agc026 题解

AGC009题解

AGC 053 C Random Card Game 题解