- 题意:有\(n\)个数对\((A_i, B_i)\),求$ \sum_{i = 1}^{n} \sum_{j = i+1}^{n} \tbinom{A_i + A_j + B_i + B_j}{A_i + A_j} $ 并且\(0 < A_i,B_i <= 2000\).
- 题解:有一个我跟本不知道的性质,即\(\tbinom{x + y}{x}\)就是指从点\((0, 0)\)只能向上或者向右,走到点\((x, y)\)的所有方案。既然这样,那么就可以从\(A_i\)和\(B_i\)的大小来确定复杂度了,但是如果就设\(dp[i][j]\)就是从原点到\((i, j)\)的方案,
我也不会知道咋算就是想,如果只是求一个\(\tbinom(n, m)\)那么结果就是让\(dp[0][0] = 1\),然后进行状态转移方程\(dp[i][j] = dp[i][j] + dp[i-1][j] + dp[i][j-1]\), \(dp[n][m]\)就是答案,但是如果我们这样,让\(dp[0+x][0+y] = 1\),然后再进行状态转移方程,其实\(\tbinom(n, m)\)就应该是\(dp[n + x][m +y]\),这个也很重要,那么就了解了这个性质,我们让所有的起点都\(++\),然后就遍历所有终点就可以算了。因为最后注意$j > i \(所以要先减去\)j = i$的情况,再除以\(2\)即乘上\(2\)的逆元。
- 代码:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const ll N = 200009;
ll fac[N];
ll q_mi(ll a, ll k, ll mod) {
ll x = a;
ll ret = 1;
while (k) {
if (k & 1)(ret *= x )%= mod;
k >>= 1;
(x *= x) %= mod;
}return ret;
}
ll inv(ll x) {return (q_mi(x, mod - 2, mod) + mod) % mod;}
ll c(ll n,ll m) {return fac[n] * (inv(fac[m])) % mod * inv(fac[n-m]) % mod;}
ll a[N], b[N];
ll dp[5021][5021];
signed main() {
ll n;
cin >> n;
for (ll i = 1; i <= n; i++) {
cin >> a[i];
cin >> b[i];
}
for (ll i = 1; i <= n; i++) {
dp[2009-a[i]][2009-b[i]] ++;
}
for (ll i = 1; i <= 5000; i++) {
for (ll j = 1; j <= 5000; j++) {
(dp[i][j] += (dp[i-1][j] + dp[i][j-1]) % mod )%=mod;
}
}
fac[0] = 1;
for (ll i = 1; i <= N - 99; i++) (fac[i] = fac[i-1] * i % mod)%= mod;
ll ans = 0;
for (ll i = 1; i <= n; i++) {
(ans = ((ans + dp[a[i] + 2009][b[i] + 2009] )%mod- c(2 * a[i] + 2 * b[i], 2 * a[i]) ) % mod +mod) %= mod;
}
(ans *= inv(2)) %= mod;
cout << ans % mod << endl;
}