zoukankan      html  css  js  c++  java
  • [2020多校A层12.1] 礼物

    计算

    [sum_isum_{j e i}{a_i+b_i+a_j+b_jchoose{a_i+a_j}} ]

    (nle10^5,sum a_i+sum b_ile2 imes10^7)


    感觉思维非常僵化啊,当时一看就以为是BBQ hard的加强版,然后直接写了个复杂度有点爆炸的分治做法,小点做BBQ hard,大点暴力。

    然而这题并没有这么复杂,我们因为值域不是很大,所以考虑在值域上做点操作。

    考虑 (a_i+b_i+a_j+b_jchoose{a_i+a_j}) 这个式子的组合意义,其实是从 (a_i+b_i+a_j+b_j) 个物品里选 (a_i+a_j) 个,那么我们考虑分两次选这个物品,第一次从 (a_i+b_i) 里选 (t) 个,那么第二次就是从 (a_j+b_j) 里选 (a_i+a_j-t) 个,那么我们可以等价写成下面这个式子:

    [egin{aligned}=&sum_{t=0}^{a_i+a_j}{a_i+b_ichoose{t}} imes{a_j+b_jchoose a_i+a_j-t}\=&sum_{t=-a_i}^{a_j}{a_i+b_ichoose a_i+t} imes{a_j+b_jchoose a_j-t}end{aligned} ]

    (t) 如果很大左边的组合数就是 (0) ,那么 (t) 的上界变成 (b_i) ,如果 (b_i>a_j) ,那么右边的组合数就是 (0),所以不会多算。

    于是两边可以分别算和再求乘积,那么对于右边那一项可以开个桶记录和,这样就可以在 (O(sum a_i+sum b_i)) 的复杂度做完了。

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    const int N = 1e5;
    const int MAXN = 2e7;
    const int p = 1e9 + 7;
    using namespace std;
    struct thi
    {
        int a,b;
    }c[N + 5],d[N + 5];
    int n,a[N + 5],b[N + 5],ans,inv[MAXN + 1],fac[MAXN + 1],sm[MAXN * 2 + 5];
    int mypow(int a,int x){int s = 1;for (;x;x & 1 ? s = 1ll * s * a % p : 0,a = 1ll * a * a % p,x >>= 1);return s;}
    int C(int n,int m)
    {
        return 1ll * fac[n] * inv[m] % p * inv[n - m] % p;
    }
    int main()
    {
        //freopen("gift.in","r",stdin);
        //freopen("gift.out","w",stdout);
        scanf("%d",&n);
        for( int i = 1;i <= n;i++)
            scanf("%d%d",&a[i],&b[i]);
        fac[0] = 1;
        for (int i = 1;i <= MAXN;i++)
            fac[i] = 1ll * fac[i - 1] * i % p;
        inv[MAXN] = mypow(fac[MAXN],p - 2);
        for (int i = MAXN - 1;i >= 0;i--)
            inv[i] = 1ll * inv[i + 1] * (i + 1) % p;
        for (int i = 1;i <= n;i++)
        {
            for (int t = -a[i];t <= b[i];t++)
                ans += 1ll * C(a[i] + b[i],t + a[i]) * sm[-t + MAXN] % p,ans %= p;
            for (int t = -a[i];t <= b[i];t++)
                sm[t + MAXN] += C(a[i] + b[i],a[i] + t) % p,sm[t + MAXN] %= p;
        }
        cout<<(2ll * ans % p + p) % p<<endl;
        return 0;
    }
    
  • 相关阅读:
    22.json&pickle&shelve
    22.BASE_DIR,os,sys
    21.time和random
    21.模块的执行以及__name__
    21.python的模块(Module)和包(Package)
    21. 对文件进行查询修改等操作
    20.装饰器和函数闭包
    19.python基础试题(三)
    19.生产者消费者模型
    19.yield和send的区别
  • 原文地址:https://www.cnblogs.com/sdlang/p/14068221.html
Copyright © 2011-2022 走看看