[数学记录]AT1983 [AGC001E] BBQ Hard

command_block

2021-02-28 19:53:17

Personal

**题意** : 给出 $n$ 个数对 $(a_i,b_i)$ ,求下列式子的值 : $$\sum\limits_{i=1}^n\sum\limits_{j=i+1}^n\dbinom{a_i+a_j+b_i+b_j}{a_i+a_j}$$ 答案对 $10^9+7$ 取模。 $n\leq 2\times 10^5,a_i,b_i\leq 2000$ ,时限$\texttt{2s}$。 ------------ 发现 $a,b$ 较小,从此处入手。 为 $\binom{n+m}{n,m}$ 编一个组合意义 : 从 $(0,0)$ 出发,只能向上或向右走,到达 $(n,m)$ 的方案数。 于是,题目中所求的式子就可以看做 : 从 $(0,0)$ 出发,到达 $(a_i+a_j,b_i+b_j)$ 的方案数。 平移一下,即改为 : 从 $(-a_i,-b_i)$ 出发,到达 $(a_j,b_j)$ 的方案数。 于是可以改为计算两两点之间的路径条数总和。减去 $i=j$ 的贡献后除以 $2$ 即可 设 $o[x,y]$ 为到达 $(x,y)$ 的路径条数,则有如下转移 : $$o[x,y]=o[x-1,y]+o[x,y-1]+\sum_i[(-a_i,-b_i)=(x,y)]$$ 复杂度为 $O(ab+n)$。 ```cpp #include<algorithm> #include<cstdio> #define MaxM 200500 #define MaxN 4050 #define ll long long using namespace std; const int mod=1000000007,det=2001; ll powM(ll a,int t=mod-2){ ll ret=1; while(t){ if (t&1)ret=ret*a%mod; a=a*a%mod;t>>=1; }return ret; } ll fac[MaxN<<1],ifac[MaxN<<1]; ll C(int n,int m) {return fac[n]*ifac[m]%mod*ifac[n-m]%mod;} void Init(int n) { fac[0]=1; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod; ifac[n]=powM(fac[n]); for (int i=n;i;i--) ifac[i-1]=ifac[i]*i%mod; } struct Data{int a,b;}s[MaxM]; int m,o[MaxN][MaxN]; int main() { scanf("%d",&m); for (int i=1;i<=m;i++){ scanf("%d%d",&s[i].a,&s[i].b); o[det-s[i].a][det-s[i].b]++; } Init(8000); for (int i=1;i<=4002;i++) for (int j=1;j<=4002;j++) o[i][j]=(o[i][j]+o[i-1][j]+o[i][j-1])%mod; int ans=0; for (int i=1;i<=m;i++){ ans=(ans+o[det+s[i].a][det+s[i].b])%mod; ans=(ans-C((s[i].a+s[i].b)*2,s[i].a*2))%mod; }ans=1ll*(ans+mod)*((mod+1)/2)%mod; printf("%d",ans); return 0; } ```