版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/82955195
传送门
题上说了那么多。
其实就是求:
我们知道
可以对应二维平面内规定每次只能向上或者向右走,最终从
到
的方案数量。
那么
就可以对应从
到
的方案数。
这样递推一个
数组表示方案数。
那么
就等于
减去
到
的方案数。
后者可以直接组合数一波。
前者用
预处理就行了。
代码:
#include<bits/stdc++.h>
#define N 200005
#define M 4005
#define mod 1000000007
#define ll long long
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int n,f[M][M],a[N],b[N];
ll ans=0,ifac[8005],fac[8005];
inline ll calc(int a,int b){return fac[a]*ifac[b]%mod*ifac[a-b]%mod;}
int main(){
n=read();
for(int i=1;i<=n;++i)a[i]=read(),b[i]=read(),++f[2001-a[i]][2001-b[i]];
for(int i=1;i<=4001;++i)for(int j=1;j<=4001;++j)f[i][j]=(f[i][j]+f[i-1][j]+f[i][j-1])%mod;
fac[0]=1,ifac[1]=1;
for(int i=1;i<=8002;++i)fac[i]=fac[i-1]*1ll*i%mod;
for(int i=2;i<=8002;++i)ifac[i]=(mod-mod/i)*ifac[mod%i]%mod;
for(int i=2;i<=8002;++i)(ifac[i]*=ifac[i-1])%=mod;
for(int i=1;i<=n;++i)(ans+=f[2001+a[i]][2001+b[i]])%=mod;
for(int i=1;i<=n;++i)ans=((ans-calc((a[i]+b[i])<<1,b[i]<<1))%mod+mod)%mod;
ans=ifac[2]*ans%mod;
cout<<ans;
return 0;
}