[JZOJ6080]【GDOI2019模拟2019.3.23】IOer【生成函数】【数学】

37 篇文章 0 订阅
35 篇文章 0 订阅

Description

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

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

T组数据。
n ≤ 1 0 18 , m ≤ 200000 , u , v ≤ 1 0 9 , T ≤ 5 n\leq 10^{18},m\leq 200000,u,v\leq 10^9,T\leq 5 n1018,m200000,u,v109,T5,答案对998244353取模

Solution

容易列出每一天的一般生成函数为 1 1 − ( u i + v ) x 1\over 1-(ui+v)x 1(ui+v)x1

那么答案就是 ∏ i = 1 m 1 1 − ( u i + v ) x \prod\limits_{i=1}^{m}{1\over 1-(ui+v)x} i=1m1(ui+v)x1 x n x^n xn这一项的系数

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

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

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

我们先给出一个结论
最终的多项式 S ( x ) = 1 ( u x ) m − 1 ∑ i = 1 m a m , i 1 − ( u i + v ) x S(x)={1\over (ux)^{m-1}}\sum\limits_{i=1}^{m}{a_{m,i}\over 1-(ui+v)x} S(x)=(ux)m11i=1m1(ui+v)xam,i
其中 a m , i a_{m,i} am,i是与m,i有关的常数

这是怎么得来的呢?
我们考虑这样一个小学奥数的式子
1 a × 1 b = 1 b − a × ( 1 a − 1 b ) {1\over a}\times{1\over b}={1\over b-a}\times({1\over a}-{1\over b}) a1×b1=ba1×(a1b1)

也就是说我们能将乘化成加减
现在的问题是求出系数 a a a,以及搞清楚前面的 1 x m − 1 1\over x^{m-1} xm11是怎么来的

我们假定已经求出了 S i ( x ) = ∏ j = 1 m 1 1 − ( u j + v ) x = 1 x i − 1 ∑ j = 1 i a i , j 1 − ( u j + v ) x S_i(x)=\prod\limits_{j=1}^{m}{1\over 1-(uj+v)x}={1\over x^{i-1}}\sum\limits_{j=1}^{i}{a_{i,j}\over 1-(uj+v)x} Si(x)=j=1m1(uj+v)x1=xi11j=1i1(uj+v)xai,j

我们要在末尾乘上 1 1 − ( u ( i + 1 ) + v ) x 1\over {1-(u(i+1)+v)x} 1(u(i+1)+v)x1
考虑它与第j项相乘

(1) a i , j 1 − ( u j + v ) x × 1 1 − ( u ( i + 1 ) + v ) x \tag 1{a_{i,j}\over 1-(uj+v)x}\times {1\over {1-(u(i+1)+v)x}} 1(uj+v)xai,j×1(u(i+1)+v)x1(1)
(2) = a i , j u x ( j − ( i + 1 ) ) × ( 1 1 − ( u j + v ) x − 1 1 − ( u ( i + 1 ) + v ) x ) \tag 2={a_{i,j}\over ux(j-(i+1))}\times \left({1\over 1-(uj+v)x}-{1\over {1-(u(i+1)+v)x}}\right) =ux(j(i+1))ai,j×(1(uj+v)x11(u(i+1)+v)x1)(2)

我们发现,分母中的x同时将会出现在后面括号的两项中,因此每加入一个新的i+1,总的式子就会除以x,这就是 1 x m − 1 1\over {x^{m-1}} xm11的来由,u也是一样的,因此我们可以提出一个 1 u m − 1 1\over u^{m-1} um11

观察a的变化,我们发现每加入一个(i+1)它就会类似的这样变动
也就是说 (3) a i + 1 , j = a i , j ( j − ( i + 1 ) ) \tag 3a_{i+1,j}={a_{i,j}\over (j-(i+1))} ai+1,j=(j(i+1))ai,j(3)

那么 a m , j = a j , j ( − 1 ) m − j ( m − j ) ! a_{m,j}={a_{j,j}(-1)^{m-j}\over (m-j)!} am,j=(mj)!aj,j(1)mj

现在的问题是计算 a i , i a_{i,i} ai,i,记为 f i f_i fi
1~i-1的每一项都会对fi有贡献
容易看出 (4) f i = ∑ j = 1 i − 1 a i − 1 , j u ( i − j ) = ∑ j = 1 i − 1 f j ( − 1 ) i − 1 − j ( i − j ) ! = − ∑ j = 1 i − 1 f j ( − 1 ) i − j ( i − j ) ! \tag 4f_i=\sum\limits_{j=1}^{i-1}{a_{i-1,j}\over u(i-j)}=\sum\limits_{j=1}^{i-1}{f_j(-1)^{i-1-j}\over (i-j)!}=-\sum\limits_{j=1}^{i-1}{f_j(-1)^{i-j}\over (i-j)!} fi=j=1i1u(ij)ai1,j=j=1i1(ij)!fj(1)i1j=j=1i1(ij)!fj(1)ij(4)

F ( x ) F(x) F(x) f i f_i fi的生成函数,我们可以得到 F ( x ) = F ( x ) e − x + x F(x)=F(x)e^{-x}+x F(x)=F(x)ex+x(因为第一项不能被转移来)

解得 F ( x ) = x e x F(x)=xe^x F(x)=xex,即 f i = 1 ( i − 1 ) ! f_i={1\over (i-1)!} fi=(i1)!1

现在有了 f f f,就能相应的计算出 a m , j a_{m,j} am,j,就能求得每一个和式的系数,进而直接利用生成函数 1 1 − a x 1\over 1-ax 1ax1的第 i i i项为 a i x a^ix aix的性质就能算出答案。

注意由于前面乘了一个 1 x m − 1 1\over x^{m-1} xm11,因此计算的是 x n + m x^{n+m} xn+m这一项。

时间复杂度 O ( m log ⁡ n ) O(m\log n) O(mlogn) log ⁡ n \log n logn是快速幂

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);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值