题解:P11817 [PA 2019 Final] 数图 / Grafy
考虑邻接矩阵,相当于一个
先容斥,钦定对角线的一个子集
好做的形式是对角线的子集
具体地,把钦定的子集减一后,剩下的限制:
记
状态数是
容斥的时候钦定对角线的子集
因此总时空复杂度
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define debug(x) (cerr<<#x": "<<(x)<<endl)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
bool ST;
const int N=510;
int f[N][N][N];
int n;ll P;
ll CC[N][N];ll C(ll x,ll y){return (x>=y&&y>=0)?CC[x][y]:0;}
bool ED;
int32_t main(){
debug(fabs(&ST-&ED)/(1<<20));
cin.tie(nullptr)->sync_with_stdio(false);
cin>>n>>P;
rep(i,0,n) CC[i][0]=1;
rep(i,1,n) rep(j,1,i) CC[i][j]=(CC[i-1][j-1]+CC[i-1][j])%P;
int k;
f[0][0][0]=1;
rep(i,0,n) for(int j=0;i+j<=n;j++) rep(l,0,n){
k=i+2*j-2*l;if(k<0) continue;
if(i==0){
if(j==0&&k==0) continue;
if(k>=2) f[i][j][l]=(f[i][j][l]+(ll)f[i][j-1][l]*(k*(k-1)/2))%P;
if(k>=1&&l>=1) f[i][j][l]=(f[i][j][l]+(ll)f[i][j-1][l-1]*k*l)%P;
if(l>=2) f[i][j][l]=(f[i][j][l]+(ll)f[i][j-1][l-2]*(l*(l-1)/2))%P;
}
else{
f[i][j][l]=(f[i][j][l]+(ll)f[i-1][j][l]*k)%P;
f[i][j][l]=(f[i][j][l]+(ll)f[i-1][j][l-1]*l)%P;
}
}
ll ans=0;
rep(i,0,n){
ll ret=0;
rep(j,0,n-i) (ret+=C(n-i,j)*f[i][n-i-j][n-i-j])%=P;
ret=ret*C(n,i)%P;
if(i&1) (ans+=P-ret)%=P;
else (ans+=ret)%=P;
}
cout<<ans<<'\n';
return 0;
}