题目大意:
有数列:
fm,n=⎧⎩⎨⎪⎪an,n=1...m∑k=1m(a−1)fm,n−k−1(1)
(1)
f
m
,
n
=
{
a
n
,
n
=
1...
m
∑
k
=
1
m
(
a
−
1
)
f
m
,
n
−
k
−
1
求:
hash=∑i=1mfi,nbasei
h
a
s
h
=
∑
i
=
1
m
f
i
,
n
b
a
s
e
i
。
其中:
n≤1e9,m≤200
n
≤
1
e
9
,
m
≤
200
或
n≤3e6,m≤1e9
n
≤
3
e
6
,
m
≤
1
e
9
解题思路:
前一部分可以用特征多项式优化常系数线性递推做,主要是第二部分。
主要是要求 m<n m < n 的 Fm,n F m , n ,当 m≥n,fm,n m ≥ n , f m , n 都是 an a n ,求hash直接等比数列求和即可。
注意如果把非正数项都看作0,除了 fm,1、fm,m+1 f m , 1 、 f m , m + 1 ,都有 fm,n=afm,n−1−(a−1)fn−m−1,m f m , n = a f m , n − 1 − ( a − 1 ) f n − m − 1 , m
考虑
fm
f
m
的生成函数
Fm(x)=∑k=0∞fm,i
F
m
(
x
)
=
∑
k
=
0
∞
f
m
,
i
,根据上述特点,有:
F=axF−(a−1)xm+1F+ax−axm+1
F
=
a
x
F
−
(
a
−
1
)
x
m
+
1
F
+
a
x
−
a
x
m
+
1
(第1项少算了a,第m+1项多算了a,要特殊考虑)。
解得:
F=ax−axm+11−ax+(a−1)xm+1 F = a x − a x m + 1 1 − a x + ( a − 1 ) x m + 1
由泰勒展开 11−x=1+x+x2+x3+... 1 1 − x = 1 + x + x 2 + x 3 + . . . ,所以有:
F=(ax−axm+1)∑k=0∞(ax+(1−a)xm+1)k F = ( a x − a x m + 1 ) ∑ k = 0 ∞ ( a x + ( 1 − a ) x m + 1 ) k
不妨设
G=∑k=0∞(ax+(1−a)xm+1)k
G
=
∑
k
=
0
∞
(
a
x
+
(
1
−
a
)
x
m
+
1
)
k
,那么
F=(ax−axm+1)G
F
=
(
a
x
−
a
x
m
+
1
)
G
。
所以
F
F
的n次方系数。
所以考虑如何求
G
G
的n次方系数。
把
G
G
用二项式展开:
直接枚举 i i ,那么,根据调和级数求和,对所有 m<n m < n 求 Gm,n G m , n 复杂度为 O(nlogn) O ( n l o g n ) 。
完结撒花,贴上代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=3000005,M=505,mod=998244353,base=19260817;
int n,a;
struct Poly
{
ll a[M];int deg;
Poly(){memset(a,0,sizeof(a));}
inline friend Poly mul(const Poly &A,const Poly &B,const Poly &C)
{
Poly res;res.deg=A.deg+B.deg;
for(int i=0;i<=A.deg;i++)
for(int j=0;j<=B.deg;j++)
res.a[i+j]=(res.a[i+j]+A.a[i]*B.a[j])%mod;
for(int i=res.deg;i>=C.deg;i--)
for(int j=0;j<=C.deg;j++)
res.a[i-C.deg+j]=(res.a[i-C.deg+j]-res.a[i]*C.a[j])%mod;
res.deg=C.deg;
return res;
}
inline friend Poly Pow(Poly A,int b,const Poly &C)
{
Poly res;res.a[0]=1,res.deg=C.deg;
for(;b;b>>=1,A=mul(A,A,C))
if(b&1)res=mul(res,A,C);
return res;
}
};
int calc(int m)
{
Poly A,B,C;
A.a[0]=B.a[1]=C.a[m]=1;
A.deg=B.deg=C.deg=m;
for(int i=1;i<=m;i++)A.a[i]=A.a[i-1]*a%mod;
if(n<=m)return A.a[n];
for(int i=0;i<m;i++)C.a[i]=1-a;
B=Pow(B,n-1,C);
int res=0;
for(int i=0;i<m;i++)res=(res+B.a[i]*A.a[i+1])%mod;
return (res+mod)%mod;
}
void solve1(int m)
{
ll ans=0,bs=1,g;
for(int i=1;i<=m;i++)
{
bs=bs*base%mod;
g=calc(i);
ans=(ans+g*bs)%mod;
}
printf("%d\n",ans);
}
ll fac[N],fac_inv[N],bin1[N],bin2[N];
int Pow(ll x,int y)
{
ll res=1;
for(;y;y>>=1,x=x*x%mod)
if(y&1)res=res*x%mod;
return res;
}
int C(int x,int y){return fac[x]*fac_inv[y]%mod*fac_inv[x-y]%mod;}
int G(int m,int n)
{
ll res=0;
for(int i=0;i*m<=n;i++)
{
int k=n-i*m;
if(k<i)continue;
res=(res+bin1[k-i]*bin2[i]%mod*C(k,i))%mod;
}
return res;
}
void solve2(int m)
{
ll g,bs=1,ans=0;
fac[0]=bin1[0]=bin2[0]=1;
for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;
for(int i=1;i<=n;i++)bin1[i]=bin1[i-1]*a%mod;
for(int i=1;i<=n;i++)bin2[i]=bin2[i-1]*(1-a+mod)%mod;
fac_inv[n]=Pow(fac[n],mod-2);
for(int i=n-1;i>=0;i--)fac_inv[i]=fac_inv[i+1]*(i+1)%mod;
for(int i=1;i<n&&i<=m;i++)
{
bs=bs*base%mod,g=(ll)a*(G(i,n-1)-G(i,n-i-1)+mod)%mod;
ans=(ans+g*bs)%mod;
}
if(n<=m)
{
bs=bs*base%mod;
g=bs*(Pow(base,m-n+1)-1)%mod*Pow(base-1,mod-2)%mod;
ans=(ans+bin1[n]*g)%mod;
}
printf("%d\n",ans);
}
int main()
{
//freopen("lx.in","r",stdin);
int m=getint();a=getint(),n=getint();
if(m<=200)solve1(m);
else solve2(m);
return 0;
}