NOI2019アナログ2019年6月27日] [B(整数分割+生成機能DP |多項式EXP)

説明:


\(1 <= N、K <= 1E5、MOD〜1E9 + 7 \)

ソリューション:


DPは、最も古典的な配置は、それぞれが最初に挿入されたと見なさ\(Iは\)多数、それは逆の数が増加することができる\(I - 0 1 \)

機能を生成すると、取得するのは簡単です:

\(ANS = \ prod_ {i = 0} ^ {N-1}(\ sum_ {J = 0} ^ IX ^ J)[X ^ K] \)

\(= \ prod_ {i = 1} ^ {n}は{1-x ^ I \オーバー1-x} [X ^ K] \)

分母は、生成関数の古典であります:

\({1 \ 1-Xオーバー} ^ N =(\ sum_ {I> = 0} X ^ I)^ N = \ sum_ {iが> = 0} C_ {I + N-1} ^ {N-1 } \)

問題はその後の要求のようになります。

\(\ prod_ {i = 1 } ^ {n}は{1-x ^ I} \) 最初のk個のエントリ。

DPは、整数除算を使用することを検討別に対応する数に分割され、K <= N及び係数の数である\((--1)} ^ {カウント数\)

DP来ることは困難ではありません。

セット\(F [i]の[J] \)私は、分割された数を表し、すべてのプログラムとj係数について。

转移([I] [j]はfは= F [i]が[JI] -f [I-1] [JI] + [I-1] [J-(N + 1)] \ F)\

ための\(I <= \ SQRT {2K} \) それほど複雑である\(O(K \ SQRT K)\)

別の多項式EXPアプローチ:

Lnはこの式は、最後の再EXPのバックかもしれません。

我々はそれを知っています:

\(LN(1 + X)\)

$ = \ int型〜LN(1 + x)の」$

\(= \ INT〜{1 \ X + 1を超える} \)

\(= \ INT〜\ sum_ {I> = 0}( - 1)^ IX ^ iは\)

\(= \ sum_ {I> = 1} {( - 1)^ {I-1}のx ^ iは上\} \)

\(ANS = EXP(\ sum_ {i = 1} ^ N(LN(1-x ^ I)-ln(1-X)))[X ^ K] \)

\(LN(1-x ^ I)= \ sum_ {J> = 1} {( - 1)^ {(J-1)は、i}、X ^ {IJ} \ Jオーバー} \)

だから、暴力は便利なアイテムの唯一の高調波シリーズを展開します。

\(LN(1-X) \) 暴力起動共感がn倍させることができる後。

複雑\(O(N〜N-ログ)\)が、MTTを書き、とても遅い巨大な、と書くことが困難を実行します。

コード:

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i <  B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

const int mo = 1e9 + 7;

ll ksm(ll x, ll y) {
    ll s = 1;
    for(; y; y /= 2, x = x * x % mo)
        if(y & 1) s = s * x % mo;
    return s;
}

const int N = 1e5 + 5;

int n, k, m;
ll fac[N * 2], nf[N * 2];
ll f[450][N];
ll g[N];
void calc(int n) {
    fac[0] = 1; fo(i, 1, n) fac[i] = fac[i - 1] * i % mo;
    nf[n] = ksm(fac[n], mo - 2); fd(i, n, 1) nf[i - 1] = nf[i] * i % mo;
}
ll C(int n, int m) {
    return fac[n] * nf[n - m] % mo * nf[m] % mo;
}

int main() {
    freopen("b.in", "r", stdin);
    freopen("b.out", "w", stdout);
    calc(200000);
    scanf("%d %d", &n, &k);
    m = sqrt(2 * k);
    f[0][0] = 1;
    fo(i, 1, m) {
        fo(j, i, k) {
            f[i][j] = f[i][j - i] - f[i - 1][j - i];
            if(j >= n + 1) f[i][j] += f[i - 1][j - (n + 1)];
            f[i][j] %= mo;
        }
    }
    ll ans = 0;
    fo(i, 0, k) {
        fo(j, 0, m) g[i] += f[j][i];
        g[i] %= mo;
        ans += g[i] * fac[n - 1 + (k - i)] % mo * nf[k - i] % mo;
    }
    ans = (ans % mo * nf[n - 1] % mo + mo) % mo;
    pp("%lld\n", ans);
}

おすすめ

転載: www.cnblogs.com/coldchair/p/11122836.html