[AGC001E] BBQ Hard

AT 的题质量就是高。

首先我们发现题目要我们求 \(\displaystyle\sum_{i=1}^{n}\sum_{j=i+1}^{n} \binom{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 \neq 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\n", 1ll * ans * fastpow(2, mod - 2) % mod);
}
int main() {
  int _ = 1;
  // scanf("%d", &_);
  while(_--) work();
  return 0;
}
posted @ 2020-09-12 22:41  Nylch  阅读(63)  评论(0编辑  收藏  举报