AGC001

E - BBQ Hard

  • 题意:有\(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;
}
posted @ 2021-01-28 13:55  u_yan  阅读(41)  评论(0编辑  收藏  举报