[Combinatorics] [polynomial] [Lagrange] count

  • From ditoly uncle FJ provincial team training courseware

Statement

  • There \ (m \) positive integer variables, find how many values program

  • Such that all variables and not more than \ (S \)

  • And the front \ (n-\) values of variables does not exceed \ (T \)

  • The answer to \ (9 + 10 ^ 7 \) modulo

  • \ (mn \ le1000 \) , \ (m \ 10 ^ 9 \) , \ (t \ 10 ^ 5 \) , \ (s \ s the \ 10 ^ {18} \)

Solution

  • Because of \ (NT \ S Le \ Le 18 is 10 ^ {} \) , so our solution can be expressed as:

  • \[\sum_{x_1=1}^t\sum_{x_2=1}^t\dots\sum_{x_n=1}^t\binom{S-\sum_{i=1}^nx_i}{m-n}\]

  • \(s=S-(m-n)+1-\sum_{i=1}^nx_i\)

  • Noting the number of combinations of the above formula and which is about \ (S \) polynomial, in particular, it is equal to \ (\ frac {s ^ { \ overline {mn}}} {(mn)!} \)

  • Wherein \ (n ^ {\ overline m } \) represents \ (n-\) a \ (m \) times increase in power, i.e., \ (\ prod_ {i = 0 } ^ {m-1} (n + i) \ )

  • It can be obtained by a function to generate a first type Stirling number, the polynomial \ (I \) order term coefficient \ (\ frac {\ begin { bmatrix} mn \\ i \ end {bmatrix}} {(mn) !} \) , where \ (\ begin {bmatrix} n \\ m \ end {bmatrix} \) is the Stirling number of the first type, i.e. the \ (n-\) elements into \ (m \) round program number arrayed

  • After the composition expressed as the number of polynomial form, we determined if we consider the first \ (n-\) variables for all \ (t ^ n \) corresponding to the kinds of values \ (S ^ I \) ( \ ( 0 \ Le i \ Le Mn \) ) the sum, then the problem can be a good solution

  • Consider the DP: \ (F [I] [J] \) represents \ (x_ {1 \ dots i } \) and all values \ ((S-m + n + 1- \ sum_ {k = 1} ^ ix_k ) ^ j \) and

  • From the viewpoint of how \ (f [i] \) was transferred to \ (f [i + 1] \)

  • I.e. the transfer enumeration \ (x_ {i + 1} \) values, set \ (s = S-m + n + 1- \ sum_ {k = 1} ^ ix_k \)

  • It can be found:

  • \[\sum_{k=1}^t(s-k)^j=\sum_{k=0}^j(-1)^{j-k}\binom jks^ksum(j-k,t)\]

  • Wherein \ (SUM (P, n-) = \ sum_ = {I}. 1 ^ Ni ^ P \) , may utilize interpolation \ (O (p) \) is determined

  • So we have a DP transfer:

  • \[f[i+1][j]=\sum_{k=0}^j(-1)^{j-k}\binom jksum(j-k,t)f[i][k]\]

  • The number of combinations apart:

  • \[\frac{f[i+1][j]}{j!}=\sum_{k=0}^j\frac{(-1)^{j-k}sum(j-k,t)}{(j-k)!}\frac{f[i][k]}{k!}\]

  • Provided polynomial \ (F_i (X) = \ sum_ {J = 0} ^ {Mn} F [I] [J] X ^ J \) , \ (G (X) = \ sum_ {I = 0} ^ {Mn } \ frac {! (- 1 ) ^ isum (i, t)} {i} x ^ i \)

  • Then it is easy to get \ (F_n (X) = G (X) n-^ \) , power to the rapid multiplication

  • Complexity \ (O ((mn) ^ 2 \ log n) \) or \ (O ((mn) ^ 2) \)

Code

#include <bits/stdc++.h>

const int N = 1010, rqy = 1e9 + 7;

typedef long long ll;

ll s;
int t, n, m, l, pw[N][N], f[N], fac[N], inv[N], invt[N], g[N], ans, S[N][N];

int qpow(int a, int b)
{
    int res = 1;
    while (b)
    {
        if (b & 1) res = 1ll * res * a % rqy;
        a = 1ll * a * a % rqy;
        b >>= 1;
    }
    return res;
}

int calc(int T)
{
    int sum = 0, res = 0, al = 1;
    for (int i = 1; i <= T + 2; i++) al = 1ll * al * (t - i + rqy) % rqy;
    for (int i = 1; i <= T + 2; i++)
    {
        sum = (sum + pw[i][T]) % rqy;
        if (i == t) return sum;
        int delta = 1ll * al * invt[i] % rqy *
            inv[i - 1] % rqy * inv[T + 2 - i] % rqy;
        if (T + 2 - i & 1) delta = (rqy - delta) % rqy;
        res = (1ll * delta * sum + res) % rqy;
    }
    return res;
}

int main()
{
    std::cin >> s >> t >> n >> m;
    l = m - n; s -= l - 1;
    f[0] = fac[0] = inv[0] = inv[1] = 1;
    for (int i = 1; i <= l + 2; i++) fac[i] = 1ll * fac[i - 1] * i % rqy;
    for (int i = 2; i <= l + 2; i++)
        inv[i] = 1ll * (rqy - rqy / i) * inv[rqy % i] % rqy;
    for (int i = 2; i <= l + 2; i++) inv[i] = 1ll * inv[i] * inv[i - 1] % rqy;
    for (int i = 1; i <= l + 2; i++)
    {
        pw[i][0] = 1;
        for (int j = 1; j <= l; j++) pw[i][j] = 1ll * pw[i][j - 1] * i % rqy;
    }
    for (int i = 1; i <= l + 2; i++) invt[i] = qpow((t - i + rqy) % rqy, rqy - 2);
    for (int i = 1; i <= l; i++) f[i] = s % rqy * f[i - 1] % rqy;
    for (int i = 0; i <= l; i++) f[i] = 1ll * f[i] * inv[i] % rqy;
    for (int i = 0; i <= l; i++)
    {
        g[i] = 1ll * calc(i) * inv[i] % rqy;
        if (i & 1) g[i] = (rqy - g[i]) % rqy;
    }
    while (n)
    {
        if (n & 1) for (int i = l; i >= 0; i--)
        {
            f[i] = 1ll * f[i] * g[0] % rqy;
            for (int j = 1; j <= i; j++)
                f[i] = (1ll * f[i - j] * g[j] + f[i]) % rqy;
        }
        for (int i = l; i >= 0; i--)
        {
            g[i] = 1ll * g[i] * g[0] % rqy;
            if (i) g[i] = (g[i] + g[i]) % rqy;
            for (int j = 1; j < i; j++)
                g[i] = (1ll * g[i - j] * g[j] + g[i]) % rqy;
        }
        n >>= 1;
    }
    S[0][0] = 1;
    for (int i = 1; i <= l; i++)
        for (int j = 1; j <= i; j++)
            S[i][j] = (1ll * S[i - 1][j] * (i - 1) + S[i - 1][j - 1]) % rqy;
    for (int i = 0; i <= l; i++)
        ans = (1ll * f[i] * fac[i] % rqy * S[l][i] + ans) % rqy;
    return std::cout << 1ll * ans * inv[l] % rqy << std::endl, 0;
}

Guess you like

Origin www.cnblogs.com/xyz32768/p/11953280.html