[羅谷P4463] CALC(生成関数)

まず、タイトルに気づく\(\)は配列が並べられ、その後、我々は唯一乗じた注文プログラムカウント\(nは!\)することができます。

た時点で明らか応答
\ [回答= [X ^ N ](1 + X)(1 + 2×)\ドット(1 + AX)= \ prod_ {i = 1} ^ A(1 + IX)\]

対数乗算、すなわち添加なる
\ [\ prod_ {i = 1
} ^ A(1 + IX)= \ EXP(\ sum_ {i = 1} ^ A \ LN(1 + IX))\] が存在\(\ LN \)拡張可能
\ [ - \のLN(1-
X)= \ sum_ {i = 1} ^ \ inftyのの\のFRAC {X ^ I} {I} \] そうある
[\ LN \(1 + IX)\\ = \ LN( 1 - ( - IX))\\ = - \ sum_ {k = 1} ^ \ inftyのの\のFRAC {( - IX)^ K}、{K} \\ = \ sum_ {K = 1} ^ \ inftyのの\のFRAC
{( - 1)^ {K + 1} I ^ K}、{K} X ^ K \] れる
\ [\ sum_ {i = 1 } ^ A \ LN(1 + IX) \\ = \ sum_ {k = 1
} ^ \ inftyの\ FRAC {( - 1)^ {K + 1} \ sum_ {i = 1} ^愛^ K}、{K} X ^ K \] 自然数力とすることができますいくつかの方法(補間、ベルヌーイ数等)を用いて算出。

最後に、多項式の経験、直接\(O(N ^ 2) \) 演算子。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 505;

int n, M, P, inv[N], Bo[N], C[N][N], a[N], b[N];

typedef vector<int> poly;

poly F[N];

int calc(const poly&a, int x)
{
    int y = 0;
    for(int i = a.size() - 1; i >= 0; i --)
        y = (1LL * y * x + a[i]) % P;
    return y;
}

int main()
{
    scanf("%d%d%d",&M,&n,&P);
    for(int i = 0; i <= n + 1; i ++)
    {
        C[i][0] = 1;
        for(int j = 1; j <= i; j ++)
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % P;
    }
    inv[1] = 1;
    for(int i = 2; i <= n + 1; i ++)
        inv[i] = (ll) inv[P % i] * (P - P / i) % P;
    Bo[0] = 1;
    for(int i = 1; i <= n; i ++)
    {
        int t = 0;
        for(int j = 0; j < i; j ++)
            t = (t + (ll)Bo[j] * C[i + 1][j]) % P;
        Bo[i] = (ll)(P - inv[i + 1]) * t % P;
    }
    F[0] = poly{0, 1};
    for(int i = 1; i <= n; i ++)
    {
        F[i].resize(i + 2);
        for(int j = 1; j <= i + 1; j ++)
        {
            F[i][j] = (ll) Bo[i + 1 - j] * C[i + 1][j] % P * inv[i + 1] % P;
            if((i + 1 - j) & 1)
                F[i][j] = (P - F[i][j]) % P;
        }
    }
    for(int i = 1; i <= n; i ++)
    {
        a[i] = (ll)inv[i] * calc(F[i], M) % P;
        if(~i&1) a[i] = (P - a[i]) % P;
    }
    for(int i = 1; i <= n; i ++)
        a[i - 1] = (ll)i * a[i] % P;
    b[0] = 1;
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 0; j < i; j ++)
            b[i] = (b[i] + (ll)b[j] * a[i - j - 1]) % P;
        b[i] = (ll)b[i] * inv[i] % P;
    }
    int ans = b[n];
    for(int i = 2; i <= n; i ++) ans = (ll)ans * i % P;
    printf("%d", ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/bestwyj/p/11626804.html