题目
分析
我们可以发现一个比较显然的结论:题目中要我们求的那个组合数就是 (−ai,−bi) 到 (aj,bj) 的方案数,知道这个结论之后就可以比较显然的转移了。
设f[i][j]表示走到这个点的方案数,转移不难想到,最后要减去重复的状态
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200005
#define M 6005
#define mod 1000000007
int n;
int A[N],B[N];
int ans;
int dp[M][M];
int jc[2 * M - 5], ny[2 * M - 5];
int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
void exgcd(int a,int b,int &x,int &y)
{
if (!b)
{
x = 1;
y = 0;
return;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
}
int NY(int a,int m)
{
int x, y;
exgcd(a, m, x, y);
return (x % m + m) % m;
}
int C(int m,int n)
{
return 1ll * jc[m] * ny[n] % mod * ny[m - n] % mod;
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
n = read();
jc[0] = jc[1] = ny[0] = ny[1] = 1;
for (int i = 2; i <= 12000; i++)
{
jc[i] = 1ll * jc[i - 1] * i % mod;
ny[i] = NY(jc[i], mod);
}
for (int i = 1; i <= n; i++)
{
A[i] = read(), B[i] = read();
dp[-A[i] + 3000][-B[i] + 3000]++;
}
for (int i = 0; i <= 6000; i++)
for (int j = 0; j <= 6000; j++)
{
if(i)
dp[i][j] = (dp[i][j] + dp[i - 1][j]) % mod;
if(j)
dp[i][j] = (dp[i][j] + dp[i][j - 1]) % mod;
}
for (int i = 1; i <= n; i++)
{
ans = (ans + dp[A[i] + 3000][B[i] + 3000]) % mod;
ans = ((ans - C(A[i] + A[i] + B[i] + B[i], A[i] + A[i])) % mod + mod) % mod;
}
ans = 1ll * ans * ny[2] % mod;
printf("%d",ans);
}