题解
我们知道 Cxy 的意义是从(0,0)出发,只能向上,向下走,走到(x,y)的方案数。
那么题目就可以变为从所有的(-ai,-bi)走到(ai,bi)的方案数。
就先给全部的(-ai,-bi)赋值为1,然后搞一个简单的dp,将全部的(ai,bi)的数加起来。
最后要去重,减掉自己到自己的,还有÷2。
code
#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define ll long long
#define N 2003
#define db double
#define P putchar
#define G getchar
#define mo 1000000007
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=n*10+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
void write(int x)
{
if(x>9) write(x/10);
P(x%10+'0');
}
int n,m,a[N*100],b[N*100],f[N*2][N*2],mxa,mxb;
ll ans,jc[N*4],ny[N*4];
ll ksm(ll x,int y)
{
ll s=1;
while(y)
{
if(y%2)s=s*x%mo;
x=x*x%mo;
y>>=1;
}
return s;
}
ll C(int x,int y)
{
return jc[y]*ny[x]%mo*ny[y-x]%mo;
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
read(n);
for(int i=1;i<=n;i++)
read(a[i]),read(b[i]),mxa=max(mxa,a[i]),mxb=max(mxb,b[i]);
jc[0]=ny[1]=1;
for(int i=1;i<=2*mxa+2*mxb;i++)
jc[i]=jc[i-1]*i%mo,ny[i]=ksm(jc[i],mo-2);
mxa++;mxb++;
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
f[mxa-a[i]][mxb-b[i]]++;
for(int i=1;i<=2*mxa;i++)
for(int j=1;j<=2*mxb;j++)
f[i][j]=(f[i][j]+(f[i-1][j]+f[i][j-1])%mo)%mo;
for(int i=1;i<=n;i++)
ans=(ans+f[mxa+a[i]][mxb+b[i]]-C(2*a[i],2*a[i]+2*b[i])+mo)%mo;
printf("%lld",ans*ksm(2,mo-2)%mo);
}