我们很容易发现。R必须为置换。
当A=B=C=0的时候,我们对于L没有限制,只要求R是个置换。
并满足
,采用dp。
最后答案即为
当A,B,C中有一个不为0的时候,L,R都是置换。
并且它们满足式子:
注意到,当我们确定了L,我们想要
是任何置换都行。
因此,求出满足条件的L,R的方案数等价于求满足
的置换
类似的,上面式子等价于
我们相当于要求出
接下来我们采用dp解决。
直接解决有点难,我们考虑间接解决。
令
我们求出
到
的方案数t1,
再求出
分解成
的方案数t2,
我们令
表示
中j个长度为i的环,
有多少种方法可以达到。
注意到,
中一个长度为
的环,会被分解成
个长度为
的环。
那么,我们枚举第一个点原来在那个大环,有递推式:
我们令
表示
中j个长度为i的环有多少中方式分解成
注意,这个时候已经确定了次序。
我们有递推式:
(想一想,为什么)
最后,我们令
背包合并一下即可。
时间复杂度:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int Mod=998244353;
typedef unsigned long long ull;
int n;
ull A,B,C;
#define Maxn 1005
int sum[Maxn];
int fact[Maxn],inv[Maxn];
vector<int> vec[Maxn];
int f[Maxn][Maxn],g[Maxn][Maxn];
int way[Maxn],Ans[Maxn];
int c[Maxn][Maxn];
ull gcd(ull a,ull b){
if(!b)return a;
return gcd(b,a%b);
}
inline int Fast_Pow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*ans*a%Mod;
a=1ll*a*a%Mod;
b>>=1;
}
return ans;
}
int main(){
c[0][0]=1;
for(register int i=1;i<=1000;++i){
c[i][0]=1;
for(register int j=1;j<=i;++j){
c[i][j]=c[i-1][j]+c[i-1][j-1];
if(c[i][j]>=Mod)c[i][j]-=Mod;
}
}
for(register int i=1;i<=1000;++i){
g[i][0]=1;
g[i][1]=i&1;
for(register int j=2;j<=1000;++j)g[i][j]=(1ll*g[i][j-1]*(i&1)+1ll*g[i][j-2]*(j-1)*i)%Mod;
}
fact[0]=1;
for(int i=1;i<=1000;++i)fact[i]=1ll*fact[i-1]*i%Mod;
inv[0]=inv[1]=1;
for(int i=2;i<=1000;++i)inv[i]=1ll*(Mod-Mod/i)*inv[Mod%i]%Mod;
for(int i=2;i<=1000;++i)inv[i]=1ll*inv[i-1]*inv[i]%Mod;
int T;
scanf("%d",&T);
while(T--){
memset(Ans,0,sizeof(Ans));
memset(f,0,sizeof(f));
scanf("%d%llu%llu%llu",&n,&A,&B,&C);
for(register int i=1;i<=n;++i)vec[i].clear();
if(A==0&&B==0&&C==0){
sum[0]=1;
for(register int i=1;i<=n;++i){
sum[i]=sum[i-1];
if(i>1)sum[i]=(sum[i]+1ll*(i-1)*sum[i-2])%Mod;
}
printf("%d\n",1ll*sum[n]*Fast_Pow(n,n)%Mod);
continue;
}
A=A+C;
if(A>=B)A-=B;
else A=B-A;
for(register int i=1;i<=n;++i){
int tmp=gcd(A,i);
vec[i/tmp].push_back(tmp);
}
Ans[0]=1;
for(register int i=1;i<=n;++i){
f[i][0]=1;
for(register int j=1;j<=n/i;++j){
for(register int k=0;k<vec[i].size();++k)
if(j>=vec[i][k])
f[i][j]=(f[i][j]+1ll*f[i][j-vec[i][k]]*fact[i*j-1]%Mod*inv[i*(j-vec[i][k])])%Mod;
else break;
}
for(register int j=0;j<=n/i;++j)way[j]=1ll*f[i][j]*g[i][j]%Mod;
for(register int j=n;j>=0;--j){
int ans=0;
for(register int k=0;k*i<=j;++k)
ans=(ans+1ll*Ans[j-k*i]*way[k]%Mod*c[j][i*k])%Mod;
Ans[j]=ans;
}
}
printf("%d\n",Ans[n]);
}
return 0;
}