题解
这一条式子其实就等价于
(∑i,jCai+ajai+aj+bi+bj−∑Cai+aiai+ai+bi+bi)/2
后面的一项显然可以暴力求,现在我们考虑前面的一段怎么求
考虑到任意一个C其实就等于是从(-ai,-bi)走到(aj,bj)的方案数,观察到a,b<=2000,所以我们可以设f(a,b)表示每一个(-ai,-bi)走到(a,b)的方案数的和,把每一个(-ai,bi)都挂一个1,然后直接dp即可
贴代码
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define c 2001
#define md 1000000007
#define ll long long
using namespace std;
const int maxn=2005,maxm=2e5+5;
ll a[maxm],b[maxm],f[maxn*2][maxn*2];
ll p[maxn*4];
ll i,j,k,l,m,n,x,y,z;
ll quickmi(ll x,ll y){
ll t1=1;
while (y){
if ((y & 1)==1) t1=(t1*x)%md;
x=(x*x)%md;
y=y/2;
}
return t1;
}
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%lld",&n);
fo(i,1,n){
scanf("%lld%lld",&a[i],&b[i]);
f[c-a[i]][c-b[i]]++;
}
fo(i,1,c*2) fo(j,1,c*2) f[i][j]=(f[i][j]+f[i][j-1]+f[i-1][j])%md;
fo(i,1,n) z=(z+f[c+a[i]][c+b[i]])%md;
p[0]=p[1]=1;
fo(i,2,c*4) p[i]=(p[i-1]*i)%md;
fo(i,1,n){
y=(p[a[i]+a[i]]*p[b[i]+b[i]])%md;
x=(p[a[i]+a[i]+b[i]+b[i]]*quickmi(y,md-2))%md;
z=(md+z-x)%md;
}
z=(z*quickmi(2,md-2))%md;
printf("%lld",z);
return 0;
}

本文介绍了一种利用动态规划解决组合数学中特定问题的方法。通过预处理从(-ai,-bi)到(aj,bj)的所有路径数目,进而计算出一个复杂的组合公式。文章提供了完整的C++代码实现。
382

被折叠的 条评论
为什么被折叠?



