zoukankan      html  css  js  c++  java
  • [组合数学] Codeforces 1549E The Three Little Pigs

    题目大意

    给定 (n),每次询问一个 (m),求

    [ask(m)=sum_{i=0}^{n}inom{3i}{m} ]

    (nleq 10^6),询问次数 (leq 2 imes 10^5)

    题解

    [inom{3i}{m}=[x^m](1+x)^{3i}\ ask(m)=[x^m]sum_{i=0}^n(1+x)^{3i} ]

    只要求出 (sum_{i=0}^n(1+x)^{3i}) 这个多项式,(m) 次项前的系数即为答案。

    [sum_{i=0}^{infty}(1+x)^{3i}=sum_{i=0}^{infty}[(1+x)^3]^i=frac{1}{1-(1+x)^3}\ sum_{i=n+1}^{infty}(1+x)^{3i}=(1+x)^{3n+3}sum_{i=0}^{infty}(1+x)^{3i}=frac{(1+x)^{3n+3}}{1-(1+x)^3}\ sum_{i=0}^n(1+x)^{3i}=sum_{i=0}^{infty}(1+x)^{3i}-sum_{i=n+1}^{infty}(1+x)^{3i}=frac{1-(1+x)^{3n+3}}{1-(1+x)^3}=frac{(1+x)^{3n+3}-1}{3x+3x^2+x^3} ]

    则有

    [ask(m)=[x^m]frac{(1+x)^{3n+3}-1}{3x+3x^2+x^3} ]

    分子可以组合数暴力展开,然后模拟大除法即可,时间复杂度 (O(n))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define LL long long
    
    template<typename elemType>
    inline void Read(elemType& T) {
        elemType X = 0, w = 0; char ch = 0;
        while (!isdigit(ch)) { w |= ch == '-';ch = getchar(); }
        while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        T = (w ? -X : X);
    }
    
    const LL MOD = 1000000007LL;
    const int maxn = 3000010;
    LL inv[maxn], fact[maxn], finv[maxn];
    
    void Init() {
        inv[1] = fact[0] = fact[1] = finv[0] = finv[1] = 1;
        for (int i = 2;i <= 3000005;++i) {
            inv[i] = ((-(MOD / i) * inv[MOD % i]) % MOD + MOD) % MOD;
            fact[i] = fact[i - 1] * i % MOD;
            finv[i] = finv[i - 1] * inv[i] % MOD;
        }
    }
    
    LL C(int n, int m) {
        if (m > n) return 0;
        return fact[n] * finv[m] % MOD * finv[n - m] % MOD;
    }
    
    LL f[maxn], h[maxn], g[10];
    int n, q;
    
    void Div(LL* f, int n, LL* g, LL m, LL* h) {
        for (int i = 0;i <= n;++i) {
            LL a = f[i] * inv[g[0]] % MOD;
            h[i] = a;
            for (int j = 0;j <= m;++j)
                f[i + j] = ((f[i + j] - g[j] * a % MOD) % MOD + MOD) % MOD;
        }
        return;
    }
    
    void solve() {
        for (int i = 0;i <= 3 * n + 3;++i)
            f[i] = C(3 * n + 3, i);
        f[0] = (f[0] - 1 + MOD) % MOD;
        g[1] = 3; g[2] = 3; g[3] = 1;h[0] = 1;
        Div(f + 1, 3 * n + 3 - 1, g + 1, 3 - 1, h + 1);
    }
    
    int main() {
        Init();
        Read(n);Read(q);
        solve();
        while (q--) {
            int x;Read(x);
            printf("%I64d
    ", h[x + 1]);
        }
        return 0;
    }
    
  • 相关阅读:
    【内核】linux内核启动流程详细分析【转】
    【Linux】Linux基本命令扫盲【转】
    【Linux高级驱动】linux设备驱动模型之平台设备驱动机制【转】
    【Git】Git与GitHub 入门【转】
    usbnet驱动深入分析-usb虚拟网卡host端【转】
    USB设备被识别流程【转】
    LinuxUSB驱动程序调试--009:编写应用程序---验证协议【转】
    公积金条例久拖不改是谁在博弈?
    Android事件机制全然解析
    《Java并发编程实战》第二章 线程安全性 读书笔记
  • 原文地址:https://www.cnblogs.com/AEMShana/p/15139074.html
Copyright © 2011-2022 走看看