[agc001e]BBQ hard

题意:

就是求$\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\binom{a_i+b_i+a_j+b_j}{a_i+b_i}$

$1\leq n\leq 200000$

$1\leq a_i,b_i\leq 2000$

题解:

这种题数据范围一看就是预处理答案,但是直接把和加起来的话复杂度依然是$n^2$的;

类似骗我呢那道题,可以考虑把组合数看成路径,那么上面的式子意思就是只能向右或向上走,从$(-a_i,-b_i)$走到$(a_j,b_j)$的方案数;

因为$a_i,b_i$都很小,所以可以直接dp出总的方案数:

$f[i][j]=f[i-1][j]+f[i][j-1]$

初始化时把$(-a_i,-b_i)$设为1即可;

统计答案时记得减去自己走到自己的方案数!

为了计算方便,我把所有坐标向右上平移了2000个单位。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 #define mod 1000000007
 6 #define inv_2 500000004
 7 using namespace std;
 8 typedef long long ll;
 9 ll n,ans=0,a[200001],b[200001],f[4010][4010],inv[10001],jc[10001];
10 ll fastpow(ll x,ll y){
11     int ret=1;
12     for(;y;y>>=1,x=(ll)x*x%mod){
13         if(y&1)ret=(ll)ret*x%mod;
14     }
15     return ret;
16 }
17 void _(){
18     jc[0]=1;
19     for(int i=1;i<=10000;i++)jc[i]=(ll)jc[i-1]*i%mod;
20     inv[10000]=fastpow(jc[10000],mod-2);
21     for(int i=9999;i;i--)inv[i]=(ll)(i+1)*inv[i+1]%mod;
22     inv[0]=1;
23 }
24 int C(int n,int m){
25     return (ll)jc[n]*inv[m]%mod*inv[n-m]%mod;
26 }
27 int main(){
28     _();
29     memset(f,0,sizeof(f));
30     scanf("%d",&n);
31     for(int i=1;i<=n;i++){
32         scanf("%d%d",&a[i],&b[i]);
33         f[-a[i]+2001][-b[i]+2001]++;
34     }
35     for(int i=1;i<=4001;i++){
36         for(int j=1;j<=4001;j++){
37             f[i][j]=(f[i][j]+f[i][j-1]+f[i-1][j])%mod;
38         }
39     }
40     for(int i=1;i<=n;i++){
41         ans=(ans+f[a[i]+2001][b[i]+2001])%mod;
42     }
43     for(int i=1;i<=n;i++){
44         ans=(ans-C(a[i]*2+b[i]*2,a[i]*2)+mod)%mod;
45     }
46     //ans=ans/2%mod;
47     ans=(ll)ans*inv_2%mod;
48     printf("%d\n",ans);
49     return 0;
50 }

 

posted @ 2018-09-20 20:58  DCDCBigBig  阅读(193)  评论(0编辑  收藏  举报