AT_agc051_d [AGC051D] C4 题解
考虑确定每条边有多少条正向的和反向的,然后直接 BEST 定理求。
考虑存在欧拉回路的条件,每个点的入边个数需要和出边个数相等,那么只需要枚举 \((1,2)\) 的个数便可以确定其它每种边的条数,直接做即可。
参考代码:
#include<bits/stdc++.h>
#define ll long long
#define mxn 1000003
#define md 998244353
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rept(i,a,b) for(int i=(a);i<(b);++i)
#define drep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
int a,b,c,d,c1,c2,c3,c4,d1,d2,d3,d4;
ll ans,f[5][5],fac[mxn],ifac[mxn];
ll power(ll x,int y){
ll ans=1;
for(;y;y>>=1){
if(y&1)ans=ans*x%md;
x=x*x%md;
}
return ans;
}
int solve(){
return (f[1][1]*f[2][2]%md*f[3][3]-f[1][1]*f[2][3]%md*f[3][2]-f[1][2]*f[2][1]%md*f[3][3]+f[1][2]*f[2][3]%md*f[3][1]+f[1][3]*f[2][1]%md*f[3][2]-f[1][3]*f[2][2]%md*f[3][1])%md;
}
signed main(){
cin>>a>>b>>c>>d;
fac[0]=1;
rep(i,1,1000000)fac[i]=fac[i-1]*i%md;
ifac[1000000]=power(fac[1000000],md-2);
drep(i,1000000,1)ifac[i-1]=ifac[i]*i%md;
rep(i,0,a){
c1=i,d1=a-i;
if((d1-c1+b)&1)continue;
d2=(d1-c1+b)>>1,c2=b-d2;
if((d2-c2+c)&1)continue;
d3=(d2-c2+c)>>1,c3=c-d3;
if((d3-c3+d)&1)continue;
d4=(d3-c3+d)>>1,c4=d-d4;
if(c4+d1!=d4+c1)continue;
if(c1<0||c1>a||c2<0||c2>b||c3<0||c3>c||c4<0||c4>d)continue;
memset(f,0,sizeof(f));
f[1][2]=-c2,f[2][1]=-d2;
f[2][3]=-c3,f[3][2]=-d3;
f[1][1]=c2+d1,f[2][2]=c3+d2,f[3][3]=c4+d3;
ans=(ans+solve()*fac[c1+d4-1]%md*fac[c2+d1-1]%md*fac[c3+d2-1]%md*fac[c4+d3-1]%md
*ifac[c1]%md*ifac[d1]%md*ifac[c2]%md*ifac[d2]%md*ifac[c3]%md*ifac[d3]%md*ifac[c4]%md*ifac[d4]%md*(c1+d4))%md;
}
cout<<(ans+md)%md;
return 0;
}

浙公网安备 33010602011771号