题目大意
有多少n*n的01矩阵每行每列恰有2个1。
推式子
设a(n)表示答案。
每次新加一行一列,你找到一行,把最后一行和它换,并在最后一列这行的位置写上1。
然后再找一行,在最后一列这写1,并找到之前一个位置的1把它翻到只有一个1的那行。
这样是n*(n-1)*a(n-1)。
你发现有种情况翻不上去,于是你枚举哪里翻不上,然后去掉那两列,这样是n*(n-1)^2*a(n-2)。
#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=10000000+10,mo=998244353;
int f[maxn];
int i,j,k,l,t,n,m,ans,inv2;
int main(){
freopen("b.in","r",stdin);freopen("b.out","w",stdout);
f[1]=0;
f[2]=1;
inv2=(mo+1)/2;
scanf("%d",&n);
fo(i,3,n){
f[i]=(ll)((ll)i*i%mo-i)%mo*f[i-1]%mo;
t=(ll)((ll)i*i%mo-i)%mo*(i-1)%mo*inv2%mo*f[i-2]%mo;
f[i]=(f[i]+t)%mo;
}
//fo(i,1,n) printf("%d\n",f[i]);
fo(i,1,n) (ans+=f[i])%=mo;
(ans+=mo)%=mo;
printf("%d\n",ans);
}