AT_abc273_g [ABC273G] Row Column Sums 2
思路
数一下读入的里面,行上有
当且仅当
无解。
设
考虑转移。
- 当
l>0 时:注意有i+2\times j=k+l\times 2 成立!
考虑分配一个 列上为
- 给行上的一个
1 和一个2 :f(i-1+1,j-1,k,l-1)\times i\times j 。(就是那个1 没了,2 变成1 了) - 给行上的两个
1 :f(i-2,j,k,l-1)\times C_i^2 。 - 给行上的两个
2 :f(i+2,j-2,k,l-1)\times C_j^2 。 - 给行上的一个
2 :f(i,j-1,k,l-1)\times j 。
当
答案就是
注意到在转移的过程中
另外因为始终有那个等式成立(不成立就无解了),所以得到
复杂度
code
#include<stdio.h>
#include<string.h>
#define mod 998244353
inline char nc()
{
static char buf[99999],*l,*r;
return l==r&&(r=(l=buf)+fread(buf,1,99999,stdin),l==r)?EOF:*l++;
}
inline void read(int&x)
{
char c=nc();for(;c<'0'||'9'<c;c=nc());
for(x=0;'0'<=c&&c<='9';x=(x<<3)+(x<<1)+(c^48),c=nc());
}
int n,a,cnt1,cnt2,cnt3,cnt4,ans[5001][5001],fac[5001];
inline long long ksm(long long a,int b)
{
long long ans=1;
for(;b;b>>=1,a*=a,a%=mod)if(b&1)ans*=a,ans%=mod;
return ans;
}
inline long long dfs(const int&i,const int&j,const int&k,const int&l)
{
if(!l)return fac[k]*ksm(ksm(2,j),mod-2)%mod;
if(~ans[i][l])return ans[i][l];
ans[i][l]=0;
if(i&&j)ans[i][l]=(ans[i][l]+dfs(i,j-1,k,l-1)*i%mod*j)%mod;
if(i>1)ans[i][l]=(ans[i][l]+dfs(i-2,j,k,l-1)*(i*(i-1ll)>>1))%mod;
if(j>1)ans[i][l]=(ans[i][l]+dfs(i+2,j-2,k,l-1)*(j*(j-1ll)>>1))%mod;
if(j)ans[i][l]=(ans[i][l]+dfs(i,j-1,k,l-1)*j)%mod;
return ans[i][l];
}
main()
{
fac[0]=1;for(int i=1;i<5001;fac[i]=(long long)(fac[i-1])*i%mod,++i);
memset(ans,-1,sizeof(ans));read(n);
for(int i=n;i--;read(a),a==1&&++cnt1,a==2&&++cnt2);
for(int i=n;i--;read(a),a==1&&++cnt3,a==2&&++cnt4);
if(cnt1+cnt2+cnt2^cnt3+cnt4+cnt4){putchar('0');return 0;}
printf("%lld",dfs(cnt1,cnt2,cnt3,cnt4));
}