luogu P5488 differential with the prefix and FFT

FFT is a good question.

First, let's take a look and find prefixes.

Seeking a prefix and roll on the first when the coefficients of a polynomial are all 1, i.e., \ (\ DisplayStyle \ sum_ {I} = 0 {^ \ Infin} X ^ I \) (Think about why), This thing is equivalent to \ (\ DisplayStyle \ {1} {FRAC-the X-1} \) , simple to prove it.
\ [S = 1 + x + x ^ 2 + ... \\ xS = x + x ^ 2 + x ^ 3 ... \\ upper equation obtained by subtracting the lower expression \\ S-xS = 1 \\ S = \ frac {1
} {1-x} \] is not feeling perfect but very nonsense? Yes, this is only \ (- 1 <x <1 \) when established. But generating functions are formal power series, we do not care about the specific values of x.

Going back to our earlier question, because convolution with a combination of law, so we ask that \ (\ displaystyle \ frac {1 } {(1-x) ^ k} \)

Conclusion: n coefficients of this equation are views \ ({C_-n-K +. 1. 1-K} ^ {} \) (C is the number of combinations).

Proof: Recall \ (\ displaystyle \ sum_ {i = 0} ^ {\ infin} x ^ i \) every multiplication meaning, found \ (\ displaystyle (\ sum_ { i = 0} ^ {\ infin } x ^ i) ^ k \ ) the meaning is the n-th coefficient k after several programs consisting of n times, we can be regarded as n balls n, k is the k as a box, because each composed of n "1" is the same, each polynomial are not the same, the same ball, different boxes, the program number is \ (C_ {n-1 + K-K-1} ^ {} \) .

Because a large k, so we need to let k modulo 1,004,535,809. As for why it is, you can quickly recall P5245 polynomial power of this question, considered in the sense die on \ (k \ times lnF (x ) \) do polynomial exponential function, it is clearly possible.

However, after the k modulo still great, we \ (C_n ^ m \) open \ (\ displaystyle C_n ^ m = \ frac {n!} {M! (Nm)!} = \ Frac {\ prod_ { = n-m +-I. 1} ^ {} {I} n-\ prod_. 1} {I = I ^ {m}} \) , and because \ (C_n ^ 0 = 1 \ ) then we can recursive composition La. \ (\ displaystyle C_k ^ i = C_k ^ {i-1} \ times \ frac {k-i + 1} {i} \)

Then take a look at determining the difference.

In fact, once the difference is equivalent to the volume \ (the X-1-\) (Think about why), So we ask that \ ((1-the X-) ^ k \) .

Seeking 1: This equation is not the feeling of deja vu? Yes, yes, we really only used to just ask \ (\ displaystyle \ frac {1 } {(1-x) ^ k} \) seeking a reverse on the line,

Seeking 2: The binomial theorem \ (\ displaystyle (1-x ) ^ k = \ sum_ {i = 0} ^ kC_ {k} ^ {i} (- x) ^ i = \ sum_ {i = 0} ^ kC_ {k} ^ {i } (- 1) ^ ix ^ i \) is then able to find it.

3 is a primitive root 1,004,535,809.

#include<bits/stdc++.h>
#define LL long long
using namespace std;
int n, opt, len;
LL k;
const int N = 400010, mod = 1004535809, G = 3, Ginv = (mod + 1) / 3;
int r[N];
LL a[N], b[N], c[N], Y[N];
char ch[2501];
int read() 
{
    int x = 0; int f = 0; char c = getchar();
    while (!isdigit(c)) f |= c == '-', c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
LL ksm(LL a, LL b, LL mod) 
{
    LL res = 1;
    for (; b; b >>= 1, a = a * a % mod)
        if (b & 1)res = res * a % mod;
    return res;
}
void NTT(LL *A, int lim, int opt) 
{
    for (int i = 0; i < lim; ++i)
        r[i] = (r[i >> 1] >> 1) | ((i & 1) ? (lim >> 1) : 0);
    for (int i = 0; i < lim; ++i)
        if (i < r[i])swap(A[i], A[r[i]]);
    int len;
    LL wn, w, x, y;
    for (int mid = 1; mid < lim; mid <<= 1) 
    {
        len = mid << 1;
        wn = ksm(opt == 1 ? G : Ginv, (mod - 1) / len, mod);
        for (int j = 0; j < lim; j += len) 
        {
            w = 1;
            for (int k = j; k < j + mid; ++k, w = w * wn % mod) 
            {
                x = A[k]; y = A[k + mid] * w % mod;
                A[k] = (x + y) % mod;
                A[k + mid] = (x - y + mod) % mod;
            }
        }
    }
    if (opt == 1)return;
    int ni = ksm(lim, mod - 2, mod);
    for (int i = 0; i < lim; ++i)A[i] = A[i] * ni % mod;
}
void MUL(LL *A, int n, LL *B, int m) 
{
    int lim = 1;
    while (lim < (n + m))lim <<= 1;
    NTT(A, lim, 1); NTT(B, lim, 1);
    for (int i = 0; i < lim; ++i)A[i] = A[i] * B[i] % mod;
    NTT(A, lim, -1);
}
void INV(int siz, LL *A, LL *B) 
{
    if (siz == 1) 
    {
        B[0] = ksm(A[0], mod - 2, mod);
        return;
    }
    INV((siz + 1) >> 1, A, B);
    int lim = 1;
    while (lim < (siz << 1))lim <<= 1;
    for (int i = 0; i < siz; ++i)c[i] = A[i];
    for (int i = siz; i < lim; ++i)c[i] = 0;
    NTT(c, lim, 1); NTT(B, lim, 1);
    for (int i = 0; i < lim; ++i)B[i] = B[i] * (2 - c[i] * B[i] % mod + mod) % mod;
    NTT(B, lim, -1);
    for (int i = siz; i < lim; ++i)B[i] = 0;
}
int main() 
{
    cin >> n; scanf("%s", ch + 1); cin >> opt;
    len = strlen(ch + 1);
    for (int i = 1; i <= len; ++i)k = k * 10 + ch[i] - '0', k %= mod;
    for (int i = 1; i <= n; ++i)a[i] = read();
    b[0] = 1;
    for (int i = 1; i <= n; ++i)b[i] = b[i - 1] * (i + k - 1) % mod * ksm(i, mod - 2, mod) % mod;
    if (opt == 0) 
    {
        MUL(a, n, b, n);
        for (int i = 1; i <= n; ++i)printf("%lld ", a[i]);
    } 
    else 
    {
        INV(n + 1, b, Y);
        MUL(a, n, Y, n);
        for (int i = 1; i <= n; ++i)printf("%lld ", a[i]);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/wljss/p/12020771.html