[AGC001E] BBQ Hard
[AGC001E] BBQ Hard
考虑写出答案式 \(\sum\limits_{i < j} \dbinom{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\) 的方案数。
考虑对每个 \(i\) 统计对应的答案,此时容易得出 \(O(n V^2)\) 做法。
接下来尝试一次 dp 求出所有的答案,而这是简单的。
接下来我们只需要去掉 \(i\) 对 \(i\) 的贡献,再除以 \(2\) 即可。
时间复杂度 \(O(n + V^2)\)。
//Ad astra per aspera
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int mod=1000000007,inv_2=500000004,V=2000;
int dp_1[2*V+10][2*V+10],dp_2[2*V+10][2*V+10];
int a[200010],b[200010];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d %d",&a[i],&b[i]);
dp_1[V-a[i]][V-b[i]]++;
dp_1[V-a[i]][V-b[i]]%=mod;
}
dp_2[0][0]=1;
for(int i=0;i<=2*V;i++){
for(int j=0;j<=2*V;j++){
if(i){
dp_1[i][j]+=dp_1[i-1][j];
dp_1[i][j]%=mod;
dp_2[i][j]+=dp_2[i-1][j];
dp_2[i][j]%=mod;
}
if(j){
dp_1[i][j]+=dp_1[i][j-1];
dp_1[i][j]%=mod;
dp_2[i][j]+=dp_2[i][j-1];
dp_2[i][j]%=mod;
}
}
}
int ans=0;
for(int i=1;i<=n;i++){
ans+=dp_1[V+a[i]][V+b[i]];
ans%=mod;
ans-=dp_2[a[i]*2][b[i]*2];
ans=(ans%mod+mod)%mod;
}
printf("%lld\n",(long long)ans*inv_2%mod);
return 0;
}

浙公网安备 33010602011771号