【题解】AT1983 BBQ Hard (格路)

【题解】AT1983 BBQ Hard (格路)

题目就是要求

\[\sum_{i=1}^n \sum _{j>i}^n {a_i+b_i+a_j+b_j \choose a_i+a_j} \]

其中\(n\le 2\times 10^5,a_i,b_i\in [1,2000]\)

这个式子有很强的组合一样,一个熟练的选手应该发现这个组合数是\(x+y\choose s\)的形式,也就是对应上了格路问题。这个问题等价于从若干\((-a_i,-b_i)\)\((a_j,b_j)\)的方案数。格路问题另一个解法是值域的DP,于是我们可以简单DP得到所有\((-a_i,-b_i)\)\((a_j,b_j)\)的方案数的和。

但是有一个边界是,不能\((i->j)\),并且一个\((i,j)\)只能算一次。所以我单独算一下\(i=j\)的所以情况的方案,减去之后在除以二。

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<assert.h>
#define DEBUG(s,a) cerr<<#s" = "<<(s)<<" \n"[(a)==1]

using namespace std;  typedef long long ll;   char __buf[1<<18],*__c=__buf,*__ed=__buf;
inline int qr(){
	int ret=0,f=0,c=getchar();
	while(!isdigit(c))f|=c==45,c=getchar();
	while(isdigit(c)) ret=ret*10+c-48,c=getchar();
	return f?-ret:ret;
}
const int maxn=8000+5;
const int mod=1e9+7;
int dp[maxn][maxn],N,n,jc[maxn],inv[maxn],A[200000+1],B[200000+1];

inline int MOD(const int&x){return x>=mod?x-mod:x;}
inline int MOD(const int&x,const int&y){return 1ll*x*y%mod;}

inline int ksm(const int&ba,const int&p){
	int ret=1;
	for(int t=p,b=ba;t;t>>=1,b=MOD(b,b))
		if(t&1) ret=MOD(ret,b);
	return ret;
}

void pre(const int&n){
	jc[0]=inv[0]=1;
	for(int t=1;t<=n;++t) jc[t]=MOD(jc[t-1],t);
	inv[n]=ksm(jc[n],mod-2);
	for(int t=n-1;t;--t) inv[t]=MOD(inv[t+1],t+1);
	for(int t=1;t<=n;++t) assert(MOD(inv[t],jc[t])==1);
}

int c(const int&n,const int&m){
	if(n<m) return 0;
	return MOD(jc[n],MOD(inv[m],inv[n-m]));
}

int main(){
	n=qr();
	for(int t=1;t<=n;++t) A[t]=qr(),B[t]=qr(),N=max({N,A[t],B[t]});
	++N;
	pre(8000);
	int ans=0;
	for(int t=1;t<=n;++t) ans=MOD(ans-c(A[t]+A[t]+B[t]+B[t],A[t]+A[t])+mod),dp[N-A[t]][N-B[t]]=MOD(dp[N-A[t]][N-B[t]]+1);
	for(int t=-N+1;t<N;++t)
		for(int i=-N+1;i<N;++i)
			dp[t+N][i+N]=MOD(dp[t+N][i+N]+MOD(dp[-1+t+N][i+N]+dp[t+N][-1+i+N]));
	for(int t=1;t<=n;++t) ans=MOD(ans+dp[A[t]+N][B[t]+N]);
	ans=MOD(ans,(mod+1)/2);
	printf("%d\n",ans);
	return 0;
}



posted @ 2020-01-11 20:13  谁是鸽王  阅读(212)  评论(0编辑  收藏  举报