Link with Balls - hdu 7047 - 生成函数解法

题意

给出2n个箱子,可以从2x-1th箱子取kx个球,可以从2xth箱子取至多x个球,那么最终取m个球有几种方法。

思路

如果了解过生成函数相关知识的话,应该不难发现每个箱子都有各自的生成函数。
F ( x ) = 1 + x + x 2 + . . . . + x n     ( t h e      n − t h ) F(x) = 1 + x + x ^2+ .... + x ^n \ \ \ (the \ \ \ \ n-th ) F(x)=1+x+x2+....+xn   (the    nth)
F ( x ) = ∑ i > = 0 x i ∗ k = 1 1 − x k      ( t h e    k − t h ) F(x) = \sum_{i>=0}x ^{i*k} = \frac{1}{1 - x ^k} \ \ \ \ (the \ \ k-th) F(x)=i>=0xik=1xk1    (the  kth)
对于所有箱子对 F ( x ) F(x) F(x)求积
F ( x ) = ∏ i = 0 n ( ∑ j = 0 i x j ) ∏ i = 1 n 1 1 − x i F(x) = \frac{\prod_{i=0}^{n} (\sum_{j=0}^ix^j)}{\prod_{i=1}^{n}\frac{1}{1-x^i}} F(x)=i=1n1xi1i=0n(j=0ixj)
展开这个函数,或者直接丢给队友解
得到
∑ i = 0 ∞ C n + i i ∗ x i − ∑ i = 0 i C n + i i ∗ x n + i + 1 \sum_{i=0}^∞C_{n+i}^i*x^i - \sum_{i=0}^iC_{n+i}^i*x^{n+i+1} i=0Cn+iixii=0iCn+iixn+i+1
令指数为m,故可以分成两部分解得答案
C m + n n − C m − 1 n C_{m+n}^n-C_{m-1}^n Cm+nnCm1n
说实话,如果会推式子化简展开,生成函数直接可以跳过思维,很方便

#include "bits/stdc++.h"
#define int long long
using namespace std;
const int mod = 1e9 + 7;
const int N = 2e6;
const int MAXN = 2e6 + 10000;
int inv[MAXN];
int c[MAXN];
int qpow(int a, int b) {
    
    
    int ans = 1;
    while (b) {
    
    
        if (b & 1) ans = a * ans % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
void prework() {
    
    
    c[0] = 1;
    for (int i = 1; i < MAXN; i++) {
    
    
        c[i] = c[i - 1] * i % mod;
        inv[i] = qpow(c[i], mod - 2);
    }
}

inline void solve() {
    
    
    int T;cin >> T;
    while (T--)
    {
    
    
        int n,m;
        cin >> n >> m;
        int t;
        if (m-1 < n) t = 0;
        else t = c[m-1] * inv[m - n -1]%mod * inv[n]%mod;
        cout << (c[n+m] * inv[n] % mod*inv[m]%mod - t + mod) % mod << endl;
    }
}

signed main() {
    
    
    ios::sync_with_stdio(0);
//    freopen("input.txt","r",stdin);
    prework();
    solve();
}

猜你喜欢

转载自blog.csdn.net/weixin_45509601/article/details/119604035