Description

有m天时间,每天可以完成任意数量的事件,第i天可以完成的事件有(ui+v)种(可以同一种完成多次)

问m天总共完成n个事件的方案数。
注意每天完成的时间是有顺序的,也就是说同一天内1,2和2,1是两种不同的方案。

T组数据。
[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_数学,答案对998244353取模

Solution

容易列出每一天的一般生成函数为[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_生成函数_02

那么答案就是[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_03[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_数学_04这一项的系数

暴力乘或者分治NTT再求逆显然不能通过。

然后我们发现分母是一个常数项为1的多项式
这不禁让我们联想起常系数齐次线性递推
但是m=200000,还有5组数据,实测极限跑一分钟都跑不出来…

然而此时我们发现并没有利用(ui+v)这个性质
这里就有一些技巧了
题解给出了一个组合意义的推导方法,这里我们介绍另外一种。

我们先给出一个结论
最终的多项式[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_多项式_05
其中[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_06是与m,i有关的常数

这是怎么得来的呢?
我们考虑这样一个小学奥数的式子
[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_07

也就是说我们能将乘化成加减
现在的问题是求出系数[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_08,以及搞清楚前面的[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_生成函数_09是怎么来的

我们假定已经求出了[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_数学_10

我们要在末尾乘上[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_生成函数_11
考虑它与第j项相乘

[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_多项式_12
[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_多项式_13

我们发现,分母中的x同时将会出现在后面括号的两项中,因此每加入一个新的i+1,总的式子就会除以x,这就是[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_多项式_14的来由,u也是一样的,因此我们可以提出一个[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_多项式_15

观察a的变化,我们发现每加入一个(i+1)它就会类似的这样变动
也就是说[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_多项式_16

那么[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_生成函数_17

现在的问题是计算[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_数学_18,记为[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_19
1~i-1的每一项都会对fi有贡献
容易看出[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_20

[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_多项式_21[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_19的生成函数,我们可以得到[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_23(因为第一项不能被转移来)

解得[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_生成函数_24,即[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_数学_25

现在有了[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_26,就能相应的计算出[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_27,就能求得每一个和式的系数,进而直接利用生成函数[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_28的第[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_取模_29项为[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_生成函数_30的性质就能算出答案。

注意由于前面乘了一个[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_生成函数_09,因此计算的是[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_数学_32这一项。

时间复杂度[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_生成函数_33[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】_生成函数_34是快速幂

Code

#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 200005
#define LL long long
#define mo 998244353
using namespace std;
int t;
LL n,m,r1,r2,ny[N],js[N];

//prepare
LL ksm(LL k,LL n)
{
k=(k+mo)%mo;
LL s=1;
for(;n;n>>=1,k=k*k%mo) if(n&1) s=s*k%mo;
return s;
}

int main()
{
int t;
cin>>t;
js[0]=1;
fo(i,1,N-5) js[i]=js[i-1]*(LL)i%mo;
ny[N-5]=ksm(js[N-5],mo-2);
fod(i,N-6,0) ny[i]=ny[i+1]*(LL)(i+1)%mo;
while(t--)
{
cin>>n>>m>>r1>>r2;
LL ans=0,v=(m&1)?1:-1,u=ksm(ksm(r1,m-1),mo-2);
fo(i,1,m)
{
ans=(ans+ny[i-1]*v*ny[m-i]%mo*ksm(r1*(LL)i%mo+r2,n+m-1)%mo*u%mo)%mo,v=-v;
}
printf("%lld\n",(ans+mo)%mo);
}
}