AT 的题质量就是高。
首先我们发现题目要我们求 (displaystylesum_{i=1}^{n}sum_{j=i+1}^{n} inom{a_i+a_j+b_i+b_j}{a_i+a_j})。
然后直接预处理组合数过不了。
那么我们想想这个东西的组合意义是什么。
对,就是求从 ((0,0)) 到 ((a_i + a_j, b_i + b_j)) 的路径数量。
那么我们平移一下,就转化成求 ((-a_i,-b_i)) 到 ((a_j,b_j)) 的路径数量。
考虑 dp,初始先让所有 (dp_{-a_i,-b_i}) 加 (1),转移方程就是 (dp_{i,j}=dp_{i,j}+dp_{i-1,j}+dp_{i,j-1})
题目要求 (i eq j) 且 (i<j) 所以我们的答案就是所有的 (dp_{a_i,b_i}) 加起来,然后减去从 ((-a_i,-b_i)) 到 ((a_i, b_i)) 的路径数量,然后除以 (2)。
#include <bits/stdc++.h>
#define reg register
#define ll long long
using namespace std;
const int MAXN = 2e5 + 10;
const int MAXM = 8010;
const int mod = 1e9 + 7;
int n, a[MAXN], b[MAXN], fac[MAXM], inv[MAXM], dp[MAXM / 2 + 10][MAXM / 2 + 10], total = MAXM / 4 + 2;
int fastpow(int a, int b) {
int ret = 1;
while(b) {
if(b & 1) ret = 1ll * ret * a % mod;
b >>= 1, a = 1ll * a * a % mod;
}
return ret;
}
int getc(int n, int m) {
return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;
}
inline void work() {
fac[1] = inv[1] = 1;
for(reg int i = 2; i <= MAXM - 10; ++i) fac[i] = 1ll * fac[i - 1] * i % mod, inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
for(reg int i = 2; i <= MAXM - 10; ++i) inv[i] = 1ll * inv[i] * inv[i - 1] % mod;
scanf("%d", &n);
for(reg int i = 1; i <= n; ++i) scanf("%d%d", &a[i], &b[i]), ++dp[total - a[i]][total - b[i]];
for(reg int i = 1; i <= MAXM / 2; ++i) for(reg int j = 1; j <= MAXM / 2; ++j) dp[i][j] = (dp[i][j] + (dp[i][j - 1] + dp[i - 1][j]) % mod) % mod;
int ans = 0;
for(reg int i = 1; i <= n; ++i) ans = (ans + dp[a[i] + total][b[i] + total]) % mod, ans = (ans - getc(a[i] * 2 + b[i] * 2, a[i] * 2) + mod) % mod;
printf("%d
", 1ll * ans * fastpow(2, mod - 2) % mod);
}
int main() {
int _ = 1;
// scanf("%d", &_);
while(_--) work();
return 0;
}