• AT1983 BBQ Hard


    洛谷题目链接:BBQ Hard

    题意翻译

    有 n 个数对 ((A_i​; B_i​)),求出 $$sum_{i=1}^{n}sum_{j=i + 1}^{n}{a_i+b_i+a_j+b_j choose a_i+a_j}$$ 答案对1e9+7取模

    • (2≦N≦200,000)
    • (1≦A_i≦2000, 1≦B_i≦2000)

    题解: 考虑(C_{a_i+b_i}^{b_i})的实际意义,实际上它相当于从((0,0))出发,走到((a_i,b_i))的方案数,那么(C_{a_i+b_i+a_j+b_j}^{a_i+a_j})也就相当与从((0,0))出发,走到((a_i+a_j,b_i+b_j))的方案数.

    如何统计从((0,0))出发,走到((a_i+a_j,b_i+b_j))的方案数呢?可以用(f[i][j])表示从((0,0))出发,走到((i,j))的方案数,则有(f[i][j]=f[i-1][j]+f[i][j-1])(从左边过来或从下面过来),答案就是(f[a_i][b_i])

    考虑将坐标轴平移,将(C_{a_i+b_i+a_j+b_j}^{a_i+a_j})看做从((-a_i,-b_i))走到((a_j,b_j))的方案数.

    那么问题来了:为什么不统一从((0,0))出发,而是要将坐标轴平移呢?我们再观察上面的式子,会发现如果统一从((0,0))出发,那么就需要统计(n^2)个终点的答案,而在平移坐标轴之后只需要给(n)个起点赋初始值,最后统计(n)个终点的答案.

    但是如果这样计算相当与统计了$$sum_{i=1}{n}sum_{j=1}{n}{a_i+b_i+a_j+b_j choose a_i+a_j}$$

    要减去重复的部分,也就是答案相当与:$$sum_{i=1}^{n}sum_{j=i + 1}^{n}{a_i+b_i+a_j+b_j choose a_i+a_j}=frac{sum_{i=1}{n}sum_{j=1}{n}{a_i+b_i+a_j+b_j choose a_i+a_j}-sum_{i=1}^n{(a_i+b_i)2 choose a_i2}}{2}$$

    因为从((-a_i,-b_i))((a_j,b_j))和从((-a_j,-b_j))((a_i,b_i))的方案是一样的.

    因为起点是负数,所以可以给负数加上一个比较大的值使它在数组中下标的位置为正数.

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e5+5;
    const int BASE = 2002;
    const int mod = 1e9+7;
    
    int n, a[N], b[N], ans = 0, f[BASE*2+5][BASE*2+5], inv[N], fac[N], pinv[N];
    
    void init(){
        fac[0] = inv[0] = pinv[0] = fac[1] = inv[1] = pinv[1] = 1;
        for(int i = 2; i <= BASE*4; i++){
            fac[i] = 1ll*fac[i-1]*i%mod;
            inv[i] = 1ll*(mod-mod/i)*inv[mod%i]%mod;
            pinv[i] = 1ll*pinv[i-1]*inv[i]%mod;
        }
    }
    
    int C(int n, int m){ return 1ll*fac[n]*pinv[m]%mod*pinv[n-m]%mod; }
    
    int main(){
        ios::sync_with_stdio(false);
        cin >> n, init();
        for(int i = 1; i <= n; i++)
            cin >> a[i] >> b[i], f[BASE-a[i]][BASE-b[i]]++;
        for(int i = 1; i <= BASE*2; i++)
            for(int j = 1; j <= BASE*2; j++)
                (f[i][j] += (f[i-1][j]+f[i][j-1])%mod) %= mod;
        for(int i = 1; i <= n; i++) (ans += f[a[i]+BASE][b[i]+BASE]) %= mod;
        for(int i = 1; i <= n; i++) (ans += mod-C((a[i]+b[i])*2, b[i]*2)) %= mod;
        ans = 1ll*ans*inv[2]%mod;
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    腾讯开放平台 手机QQ登录 错误码:110406 解决办法
    比较酷的安卓软件
    Top 10 Methods for Java Arrays
    Feathers UI 性能优化
    Starling中通过PivotX 和 PivotY 修改原点
    Adobe AIR 中为不同尺寸和分辨率屏幕适配
    Feathers组件的宽度或高度属性,为什么我得到的值是0
    "Type Coercion failed" Error in FlashBuilder 4.7
    正则表达式中的特殊字符
    单体内置对象 Global 和 Math
  • 原文地址:https://www.cnblogs.com/BCOI/p/10498320.html
Copyright © 2020-2023  润新知