很简单啦,随便写写然后记忆化实现一下就好了嘛:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define db double
#define sg string
#define ll long long
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define red(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;
const ll N=2e3+5;
db f[N][N];
ll n,m,row[N],col[N];
inline ll read() {
ll x=0;char ch=getchar();bool f=0;
while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?-x:x;
}
void dfs(ll c,ll r ){
if(f[c][r]!=-1) return ;
if(!c&&!r) {
f[c][r]=0.0;return ;
}
db ret=0.0;
if(c) {
dfs(c-1,r);
ret+=(c*(n-r)*f[c-1][r]);
}
if(r) {
dfs(c,r-1);
ret+=(r*(n-c)*f[c][r-1]);
}
if(c&&r) {
dfs(c-1,r-1);
ret+=(c*r*f[c-1][r-1]);
}
f[c][r]=1.0*(ret*1.0+n*n)/(1.0*(c+r)*n-1.0*c*r);
}
void File() {
freopen("shoot.in","r",stdin);
freopen("shoot.out","w",stdout);
}
int main() {
// File();
n=read(),m=read();
rep(i,1,m) {
ll x=read(),y=read();
col[x]=1,row[y]=1;
}
ll c=0,r=0;
rep(i,1,n) if(!col[i]) c++;
rep(i,1,n) if(!row[i]) r++;
rep(i,0,n) rep(j,0,n) f[i][j]=-1.0;
dfs(c,r);
printf("%.2lf",f[c][r]);
return 0;
}