[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;
}
posted @ 2026-03-23 10:16  Oken喵~  阅读(18)  评论(0)    收藏  举报