Description
m种物品,第i种物品的权值为
(
u
i
+
v
)
(ui+v)
(ui+v),每种物品有无数个,一种取法的代价为所取物品权值乘积,
问取n个物品的所有不同取法的代价和,
两个取法不同当且仅当存在一种物品在两个方案中取得数量不同,
n ≤ 1 0 18 , m ≤ 2 ∗ 1 0 5 , m o = 1 0 9 + 7 n\leq10^{18},m\leq 2*10^5,mo=10^9+7 n≤1018,m≤2∗105,mo=109+7
Solution
显然的,我们要求这个东西的第n项:
∏
i
=
1
m
(
∑
j
=
0
(
v
i
+
u
)
j
x
j
)
\prod_{i=1}^m(\sum_{j=0}(vi+u)^jx^j)
i=1∏m(j=0∑(vi+u)jxj)
生成函数写出来:
a
n
s
=
[
x
n
]
∏
i
=
1
m
1
1
−
(
v
i
+
u
)
x
ans=[x_n]\prod_{i=1}^m\frac{1}{1-(vi+u)x}
ans=[xn]i=1∏m1−(vi+u)x1
先抛出结论(下面的构造过程就是证明):存在以下等式
设
p
i
=
(
v
i
+
u
)
p_i=(vi+u)
pi=(vi+u)
∏
i
=
1
m
1
1
−
p
i
x
=
1
(
v
x
)
m
−
1
∑
i
=
1
m
a
i
1
−
p
i
x
\prod_{i=1}^m\frac{1}{1-p_ix}=\frac{1}{(vx)^{m-1}}\sum_{i=1}^m\frac{a_i}{1-p_ix}
i=1∏m1−pix1=(vx)m−11i=1∑m1−pixai
其中
a
i
a_i
ai为系数,
还有一个东西: 1 a ∗ 1 b = ( 1 a − 1 b ) 1 b − a \frac{1}{a}*\frac{1}{b}=(\frac{1}{a}-\frac{1}{b})\frac{1}{b-a} a1∗b1=(a1−b1)b−a1
考虑增量构造,每次乘上一个
1
1
−
p
i
x
\frac{1}{1-p_ix}
1−pix1,考虑系数
a
i
a_i
ai的变化
为了方便,我们设加入第j个元素后第i位的系数为
a
j
,
i
a_{j,i}
aj,i
当前我们加入第j位:
(
v
x
)
−
j
+
1
(
∑
i
=
1
j
−
1
a
j
−
1
,
i
1
−
p
i
x
)
(
1
1
−
p
j
x
)
(vx)^{-j+1}(\sum_{i=1}^{j-1}\frac{a_{j-1,i}}{1-p_ix})(\frac{1}{1-p_jx})
(vx)−j+1(i=1∑j−11−pixaj−1,i)(1−pjx1)
(
v
x
)
−
j
+
1
∑
i
=
1
j
−
1
(
a
j
−
1
,
i
∗
1
1
−
p
i
x
∗
1
1
−
p
j
x
)
(vx)^{-j+1}\sum_{i=1}^{j-1}(a_{j-1,i}*\frac{1}{1-p_ix}*\frac{1}{1-p_jx})
(vx)−j+1i=1∑j−1(aj−1,i∗1−pix1∗1−pjx1)
用上面那个东西拆开:
(
v
x
)
−
j
+
1
∑
i
=
1
j
−
1
a
j
−
1
,
i
(
1
1
−
p
i
x
−
1
1
−
p
j
x
)
(
1
(
p
i
−
p
j
)
x
)
(vx)^{-j+1}\sum_{i=1}^{j-1}a_{j-1,i}(\frac{1}{1-p_ix}-\frac{1}{1-p_jx})(\frac{1}{(p_i-p_j)x})
(vx)−j+1i=1∑j−1aj−1,i(1−pix1−1−pjx1)((pi−pj)x1)
把最后面的p拆开:
(
v
x
)
−
j
+
1
∑
i
=
1
j
−
1
a
j
−
1
,
i
(
1
1
−
p
i
x
−
1
1
−
p
j
x
)
(
1
(
i
−
j
)
v
x
)
(vx)^{-j+1}\sum_{i=1}^{j-1}a_{j-1,i}(\frac{1}{1-p_ix}-\frac{1}{1-p_jx})(\frac{1}{(i-j)vx})
(vx)−j+1i=1∑j−1aj−1,i(1−pix1−1−pjx1)((i−j)vx1)
再把最后面那个的
1
v
x
\frac{1}{vx}
vx1提到前面,并把剩下的乘进去:
(
v
x
)
−
j
∑
i
=
1
j
−
1
a
j
−
1
,
i
−
(
j
−
i
)
1
1
−
p
i
x
+
a
j
−
1
,
i
(
j
−
i
)
1
1
−
p
j
x
(vx)^{-j}\sum_{i=1}^{j-1}\frac{a_{j-1,i}}{-(j-i)}\frac{1}{1-p_ix}+\frac{a_{j-1,i}}{(j-i)}\frac{1}{1-p_jx}
(vx)−ji=1∑j−1−(j−i)aj−1,i1−pix1+(j−i)aj−1,i1−pjx1
我们发现一开始的项又出来了,也就是
a
j
−
1
a_{j-1}
aj−1与
a
j
a_j
aj之间存在以下关系:
a
j
,
i
=
−
1
(
j
−
i
)
∗
a
j
−
1
,
i
,
当
i
<
j
a_{j,i}=-\frac{1}{(j-i)}*a_{j-1,i},当i<j
aj,i=−(j−i)1∗aj−1,i,当i<j
a
j
,
i
=
∑
k
=
1
j
−
1
1
(
j
−
k
)
∗
a
j
−
1
,
k
,
当
i
=
j
a_{j,i}=\sum_{k=1}^{j-1}\frac{1}{(j-k)}*a_{j-1,k},当i=j
aj,i=k=1∑j−1(j−k)1∗aj−1,k,当i=j
我们设
f
i
=
a
i
,
i
f_i=a_{i,i}
fi=ai,i,即i这一项第一次出现时的值,有:
f
i
=
∑
j
=
1
i
−
1
1
(
i
−
j
)
∗
a
i
−
1
,
j
=
∑
j
=
1
i
−
1
f
j
∗
(
−
1
)
i
−
j
−
1
(
i
−
j
)
!
f_i=\sum_{j=1}^{i-1}\frac{1}{(i-j)}*a_{i-1,j}=\sum_{j=1}^{i-1}f_j*\frac{(-1)^{i-j-1}}{(i-j)!}
fi=j=1∑i−1(i−j)1∗ai−1,j=j=1∑i−1fj∗(i−j)!(−1)i−j−1
不难发现,f就是个卷积式,也就是:
f
=
f
∗
(
∑
i
=
1
(
−
1
)
i
−
1
i
!
x
i
)
+
x
f=f*(\sum_{i=1}\frac{(-1)^{i-1}}{i!}x^i)+x
f=f∗(i=1∑i!(−1)i−1xi)+x
写成生产函数的形式:(一次项记得加上)
f
=
f
∗
(
1
−
e
−
x
)
+
x
f=f*(1-e^{-x})+x
f=f∗(1−e−x)+x
解得:
f
=
x
e
x
f=xe^x
f=xex
也就是:
f
i
=
1
(
i
−
1
)
!
f_i=\frac{1}{(i-1)!}
fi=(i−1)!1
解出了
f
f
f剩下的就好办了,直接算即可,
1 ( v x ) m − 1 ∑ i = 1 m ( − 1 ) m − i ( i − 1 ) ! ( m − i ) ! ∗ 1 1 − p i x \frac{1}{(vx)^{m-1}}\sum_{i=1}^m\frac{(-1)^{m-i}}{(i-1)!(m-i)!}*\frac{1}{1-p_ix} (vx)m−11i=1∑m(i−1)!(m−i)!(−1)m−i∗1−pix1
复杂度: O ( n log ( 1 0 9 ) ) O(n\log(10^9)) O(nlog(109))
Code
#include <cstdio>
#include <algorithm>
#include <iostream>
#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 efo(i,q) for(int i=A[q];i;i=B[i][0])
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
typedef long long LL;
const int N=200500,mo=998244353;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,ans;
LL n,K,nw;
LL f[N];
LL jc[N],jcn[N];
LL ksm(LL q,LL w)
{
LL ans=1;
for(;w;w>>=1,q=q*q%mo)if(w&1)ans=ans*q%mo;
return ans;
}
int main()
{
freopen("ioer.in","r",stdin);
freopen("ioer.out","w",stdout);
int q,w,_;
n=2e5;
jc[0]=1;fo(i,1,n)jc[i]=jc[i-1]*i%mo;
jcn[n]=ksm(jc[n],mo-2);fod(i,n-1,0)jcn[i]=jcn[i+1]*(i+1LL)%mo;
read(_);
while(_--)
{
scanf("%lld%d%lld%lld",&n,&m,&K,&nw);
ans=0;
fo(i,1,m)
{
nw=(nw+K)%mo;
f[i]=jcn[i-1]*jcn[m-i]%mo*((m-i)&1?-1:1);
ans=(ans+f[i]*ksm(nw,n+m-1))%mo;
}
ans=ans*ksm(ksm(K,m-1),mo-2)%mo;
printf("%lld\n",(ans+mo)%mo);
}
return 0;
}