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;
}
posted @ 2021-05-19 23:44  WWW~~~  阅读(114)  评论(0编辑  收藏  举报