無限手套(生成函數)

牛客 無限手套

輸入描述:

第一行一個正整數m表示寶石的種類(1<=m<=1000)接下來M行,每行兩個正整數ai, bi(0<=ai, bi<=10^9)接下來一行正整數q,共有q次詢問(1<=q<=1000)接下來q行每行一個正整數n詢問如果無限手套可以安裝n個寶石則力量之和是多少。(1<=n<=10000)

輸出描述:

一共q行,每行一個正整數表示答案。答案對998244353取模。

示例1

輸入

2
2 1
1 0
2
3
4

輸出

74
193

題解

考慮對每一個寶石的生成函數爲
k=0(aik2+bik+1)xk \sum_{k=0}^{\infty}(a_ik^2+b_ik+1)x^k
化簡過程:
k=0(aik2+bik+1)xk=k=0xk+bik=0kxk+aik=0k2xk=11x+bix(1x)2+aix(1+x)(1x)3=x2(aibi+1)+x(ai+bi2)+1(1x)3 \begin{aligned} &\sum_{k=0}^{\infty}(a_ik^2+b_ik+1)x^k\\ =&\sum_{k=0}^{\infty}x^k+b_i\sum_{k=0}^{\infty}kx^k+a_i\sum_{k=0}^{\infty}k^2x^k\\ =&\cfrac{1}{1-x}+\cfrac{b_ix}{(1-x)^2}+\cfrac{a_ix(1+x)}{(1-x)^3}\\ =&\cfrac{x^2(a_i-b_i+1)+x(a_i+b_i-2)+1}{(1-x)^3} \end{aligned}
其中也許令你迷惑的是k=0k2xk=x(1+x)(1x)3\displaystyle\sum_{k=0}^{\infty}k^2x^k=\cfrac{x(1+x)}{(1-x)^3}

推導過程如下:
k=0xk=11x  (x<1)     ddx(k=0xk)=1(1x)2k=0kxk1=1(1x)2k=0kxk=x(1x)2     ddx(k=0kxk)=(1x)2+2x(1x)(1x)4k=0k2xk1=1+x(1x)3     k=0k2xk=x(1+x)(1x)3 \begin{aligned} \sum_{k=0}^{\infty}x^k&=\cfrac{1}{1-x}\ \ (|x|<1)\\ \implies\ \cfrac{d}{dx}(\sum_{k=0}^{\infty}x^k)&=\cfrac{1}{(1-x)^2}\\ \sum_{k=0}^{\infty}kx^{k-1}&=\cfrac{1}{(1-x)^2}\\ \sum_{k=0}^{\infty}kx^{k}&=\cfrac{x}{(1-x)^2}\\ \implies\ \cfrac{d}{dx}(\sum_{k=0}^{\infty}kx^k)&=\cfrac{(1-x)^2+2x(1-x)}{(1-x)^4}\\ \sum_{k=0}^{\infty}k^2x^{k-1}&=\cfrac{1+x}{(1-x)^3}\\ \implies\ \sum_{k=0}^{\infty}k^2x^k&=\cfrac{x(1+x)}{(1-x)^3} \end{aligned}
m種寶石的生成函數相乘
i=1m[(aibi+1)x2+(ai+bi2)x+1](1x)3m \cfrac{\displaystyle\prod_{i=1}^{m}[(a_i-b_i+1)x^2+(a_i+b_i-2)x+1]}{(1-x)^{3m}}
最後xnx^n的係數即爲所求

代碼

// #include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <unordered_map>
#include <set>
#include <vector>
#include <assert.h>
#include <cmath>
#include <ctime>
using namespace std;
#define me(x,y) memset((x),(y),sizeof (x))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define SGN(x) ((x)>0?1:((x)<0?-1:0))
#define ABS(x) ((x)>0?(x):-(x))
// #define int __int128_t

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const int maxn = 1e5+10;
const int inf = __INT32_MAX__;
const ll INF = __LONG_LONG_MAX__;
const ll MOD = 998244353;
const double eps = 1e-8;
const double pi = std::acos(-1);
const string cars[] = {"🚗","🚕","🚙"};

ll f[maxn],finv[maxn],inv[maxn];
void init(){
    inv[1] = 1;
    for(int i = 2; i < maxn;++i) inv[i] = 1ll*(MOD-MOD/i)*inv[MOD%i]%MOD;
    f[0] = finv[0] = 1;
    for(int i = 1; i < maxn; ++i){
        f[i] = f[i-1]*i%MOD;
        finv[i] = finv[i-1]*inv[i]%MOD;
    }
}
ll comb(int n,int m){
    if(m < 0 || m > n) return 0;
    return f[n]*finv[n-m]%MOD*finv[m]%MOD;
}

ll x[maxn];
int main(){
    ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    freopen("1in.in","r",stdin);
    freopen("1out.out","w",stdout);
#endif    
    init();
    int a,b,A,B,C,m;cin>>m;
    x[0] = 1;
    for(int i = 1; i <= m; ++i){
        cin>>a>>b;
        A = a-b+1,B = a+b-2,C = 1;
        A = (A%MOD+MOD)%MOD,B = (B%MOD+MOD)%MOD;
        for(int j = 2*i; j >= 2; --j) x[j] = (x[j]*C%MOD+x[j-1]*B%MOD+x[j-2]*A%MOD)%MOD;
        x[1] = (x[1]*C%MOD+x[0]*B%MOD)%MOD;
        x[0] = x[0]*C%MOD;
    }
    int q;cin>>q;
    while(q--){
        int n;cin>>n;
        ll sum = 0;
        for(int i = 0; i <= n; ++i) sum = (sum+comb(3*m+i-1,i)*x[n-i]%MOD)%MOD;
        cout<<sum<<endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章