[AGC028D] Chords 题解
发现两条线段 \((i,j),(k,l)\) 相交当且仅当两线段在数轴上相交但不包含。那么我们就将这个问题从圆上移到了数轴上。
我们设 \(dp_{i,j}\) 表示在区间 \([i,j]\) 内各点在内部随意连边,不能向外连边的情况下,\(i,j\) 在同一联通块内的方案数,那么不容易发现答案即为 \(\sum\limits_{i=1}^{2n}\sum\limits_{j=i+1}^{2n}dp_{i,j}g(n-k-\frac{c_{i,j}}{2})\),其中 \(c_{l,r}\) 表示区间 \([l,r]\) 内没有确定和谁连边的点的个数,\(g(i)=\prod\limits_{j=1}^i(2j-1)\)。
\(dp\) 转移方程可以通过容斥的方法解决。总共的方案数为 \(g(\frac{c_{i,j}}{2})\),\(i,j\) 不联通的方案数为 \(\sum\limits_{d=i}^{j-1}dp_{i,d}g(\frac{c_{d+1,j}}{2})\),所以 \(dp\) 转移方程即为:
\[dp_{i,j}=g(\frac{c_{i,j}}{2})-\sum\limits_{d=i}^{j-1}dp_{i,d}g(\frac{c_{d+1,j}}{2})
\]
时间复杂度 \(O(n^3)\)。
#include<bits/stdc++.h>
using namespace std;
const int N=605,p=1e9+7;
int n,k,c[N],vs[N][N],g[N],dp[N][N],ans;
int cc(int l,int r){
return c[r]-c[l-1];
}int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>k,g[0]=1;
for(int i=1;i<=2*n;i++) c[i]=1;
for(int i=1,x,y;i<=k;i++){
cin>>x>>y,c[x]=0,c[y]=0;
if(x>y) swap(x,y);
for(int j=1;j<=x;j++)
for(int l=x;l<y;l++) vs[j][l]=1;
for(int j=x+1;j<=y;j++)
for(int l=y;l<=2*n;l++) vs[j][l]=1;
}for(int i=1;i<=2*n;i++) c[i]+=c[i-1];
for(int i=1;i<=n;i++) g[i]=1ll*g[i-1]*(2*i-1)%p;
for(int ln=2;ln<=2*n;ln+=2)
for(int l=1,r=ln;r<=2*n;l++,r++){
if(vs[l][r]) continue;
dp[l][r]=g[cc(l,r)/2];
for(int d=l+1;d<r;d+=2)
dp[l][r]=(dp[l][r]-1ll*g[cc(d+1,r)/2]*dp[l][d]%p+p)%p;
ans=(ans+1ll*dp[l][r]*g[n-k-cc(l,r)/2])%p;
}
return cout<<ans,0;
}

浙公网安备 33010602011771号