5358. 【NOIP2017提高A组模拟9.12】BBQ

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

题目
这里写图片描述

题解

这一条式子其实就等价于 (i,jCai+ajai+aj+bi+bjCai+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;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值