AtCoder Grand Contest 001 E - BBQ Hard

题目

这里写图片描述

分析

我们可以发现一个比较显然的结论:题目中要我们求的那个组合数就是 (ai,bi) (aj,bj) 的方案数,知道这个结论之后就可以比较显然的转移了。

设f[i][j]表示走到这个点的方案数,转移不难想到,最后要减去重复的状态

代码

#include <bits/stdc++.h>

using namespace std;  

#define ll long long
#define N 200005  
#define M 6005  
#define mod 1000000007  

int n;
int A[N],B[N];
int ans;

int dp[M][M];  

int jc[2 * M - 5], ny[2 * M - 5];  

int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    return x * f;
}

void exgcd(int a,int b,int &x,int &y)  
{  
    if (!b)
    {
        x = 1;
        y = 0;
        return;
    }  
    exgcd(b, a % b, y, x);  
    y -= a / b * x;  
}  

int NY(int a,int m)  
{  
    int x, y;  
    exgcd(a, m, x, y);  
    return (x % m + m) % m;  
} 

int C(int m,int n)  
{  
    return 1ll * jc[m] * ny[n] % mod * ny[m - n] % mod;  
}  
int main()  
{  
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    n = read();  
    jc[0] = jc[1] = ny[0] = ny[1] = 1;  
    for (int i = 2; i <= 12000; i++)  
    {  
        jc[i] = 1ll * jc[i - 1] * i % mod;  
        ny[i] = NY(jc[i], mod);  
    } 
    for (int i = 1; i <= n; i++)  
    {  
        A[i] = read(), B[i] = read();
        dp[-A[i] + 3000][-B[i] + 3000]++;  
    }  
    for (int i = 0; i <= 6000; i++)  
        for (int j = 0; j <= 6000; j++)  
        {  
            if(i)  
                dp[i][j] = (dp[i][j] + dp[i - 1][j]) % mod;  
            if(j)  
                dp[i][j] = (dp[i][j] + dp[i][j - 1]) % mod;  
        }  
    for (int i = 1; i <= n; i++)  
    {  
        ans = (ans + dp[A[i] + 3000][B[i] + 3000]) % mod;  
        ans = ((ans - C(A[i] + A[i] + B[i] + B[i], A[i] + A[i])) % mod + mod) % mod;  
    }  
    ans = 1ll * ans * ny[2] % mod;  
    printf("%d",ans);  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值