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;
    }
    
  • 相关阅读:
    8.13实习报告
    8.10实习报告
    8.9实习报告
    8.8实习报告
    8.7实习报告
    关于线索二叉树建立和遍历
    main函数的位置可以任意
    返回指针值的函数和函数指针的区别
    runtime error: store to address 0x625000002048 with insufficient space for an object of type 'double' (solution.c) 0x625000002048: note: pointer points here
    m=-n++
  • 原文地址:https://www.cnblogs.com/AEMShana/p/15139074.html
Copyright © 2011-2022 走看看