题目大意
给定数组
A
A
A的前
K
K
K位,和一个
K
K
K位的数组
C
C
C(
1
≤
K
≤
30000
1\leq K\leq 30000
1≤K≤30000),
A
i
=
∑
j
=
1
K
A
i
−
j
×
C
j
A_i=\sum_{j=1}^K A_{i-j}\times C_j
Ai=j=1∑KAi−j×Cj
求
A
N
A_N
AN(
1
≤
N
≤
1
0
18
1\leq N\leq 10^{18}
1≤N≤1018)。
subtask 1:
1
≤
K
≤
3000
1\leq K\leq3000
1≤K≤3000
subtask 2:
1
≤
K
≤
30000
1\leq K\leq 30000
1≤K≤30000
题解
本来要用 Cayley-Hamilton定理 ,奇怪的玩意儿,但我看不懂X﹏X。。。于是尝试避开这个东西来理解。
最后的结果一定是从A的前k位转移过来的,设结果:
a
n
s
=
f
1
A
1
+
f
2
A
2
+
f
3
A
3
+
.
.
.
+
f
K
A
K
ans=f_1A_1+f_2A_2+f_3A_3+...+f_KA_K
ans=f1A1+f2A2+f3A3+...+fKAK
当
N
=
1
N=1
N=1时:
f
:
1
0
0
.
.
.
0
f:\begin{matrix} 1&0&0&...&0\\ \end{matrix}
f:100...0
当
N
=
2
N=2
N=2时:
f
:
0
1
0
.
.
.
0
f:\begin{matrix} 0&1&0&...&0\\ \end{matrix}
f:010...0
相当于每次都右移1位。
直到
N
=
K
+
1
N=K+1
N=K+1
f
:
C
K
C
K
−
1
C
K
−
2
.
.
.
C
1
f:\begin{matrix} C_K&C_{K-1}&C_{K-2}&...&C_1\\ \end{matrix}
f:CKCK−1CK−2...C1
如果把
f
f
f看作多项式:
f
(
x
)
=
f
1
+
f
2
x
+
f
3
x
2
+
.
.
.
+
f
K
x
K
−
1
f(x)=f_1+f_2x+f_3x^2+...+f_Kx^{K-1}
f(x)=f1+f2x+f3x2+...+fKxK−1
右移操作就相当于将
f
(
x
)
f(x)
f(x)变为
x
f
(
x
)
xf(x)
xf(x),
如果出现了第
x
K
x^K
xK项,需要把它化为
x
0
x^0
x0~
x
K
−
1
x^{K-1}
xK−1项
x
K
=
C
K
+
C
K
−
1
x
+
C
K
−
2
x
2
+
.
.
.
+
C
1
x
K
−
1
x^K=C_K+C_{K-1}x+C_{K-2}x^2+...+C_1x^{K-1}
xK=CK+CK−1x+CK−2x2+...+C1xK−1
令
p
(
x
)
=
x
K
−
C
K
−
C
K
−
1
x
−
C
K
−
2
x
2
−
.
.
.
−
C
1
x
K
−
1
p(x)=x^K-C_K-C_{K-1}x-C_{K-2}x^2-...-C_1x^{K-1}
p(x)=xK−CK−CK−1x−CK−2x2−...−C1xK−1
实际上就是把多项式
f
(
x
)
m
o
d
p
(
x
)
f(x)\space mod\space p(x)
f(x) mod p(x),就可以把
x
K
x_K
xK及以后的项全部化为
x
0
x^0
x0~
x
K
−
1
x^{K-1}
xK−1
因为:
f
K
+
1
x
K
f_{K+1}x^K
fK+1xK取模相当于把
f
(
x
)
f(x)
f(x)变为
f
(
x
)
−
f
K
+
1
x
K
+
f
K
+
1
C
K
+
f
K
+
1
C
K
−
1
x
+
.
.
.
+
f
K
+
1
C
1
x
K
−
1
f(x)-f_{K+1}x^K+f_{K+1}C_K+f_{K+1}C_{K-1}x+...+f_{K+1}C_1x^{K-1}
f(x)−fK+1xK+fK+1CK+fK+1CK−1x+...+fK+1C1xK−1
令转移多项式
t
(
x
)
=
x
t(x)=x
t(x)=x
最终结果即为
f
=
t
N
m
o
d
p
f=t^N\space mod\space p
f=tN mod p ;
利用多项式快速幂,多项式取模可以做到
O
(
K
(
log
2
K
)
(
log
2
N
)
)
O(K(\log_2 K) (\log_2 N))
O(K(log2K)(log2N))。
推广
凡是第
i
i
i项可以由前面
k
k
k项通过常数系数得到的递推(实际上就是可以使用矩阵加速的递推),都可以转为多项式取模,若
A
i
=
∑
j
=
1
k
f
j
A
i
−
j
A_i=\sum_{j=1}^kf_jA_{i-j}
Ai=j=1∑kfjAi−j
则可以通过取模
p
(
x
)
=
x
k
−
∑
j
=
1
k
f
j
x
k
−
j
p(x)=x^k-\sum_{j=1}^kf_jx^{k-j}
p(x)=xk−j=1∑kfjxk−j
进行递推。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXK=30005,MOD=104857601,ROOT=3;
typedef int Poly[MAXK*5];
int PowMod(int a,int b)
{
int res=1;
while(b)
{
if(b&1)
res=(1LL*res*a)%MOD;
a=(1LL*a*a)%MOD;
b>>=1;
}
return res;
}
void NTT(Poly &a,int n,int mode)
{
for(int i=0,j=0;i<n;i++)
{
if(i<j)
swap(a[i],a[j]);
int k=n>>1;
while(k&&(k&j))
j^=k,k>>=1;
j^=k;
}
for(int i=1;i<n;i<<=1)
{
int w1=PowMod(ROOT,(MOD-1)/(i<<1)),w=1;
if(mode==-1)
w1=PowMod(w1,MOD-2);
for(int j=0;j<i;j++,w=(1LL*w*w1)%MOD)
for(int l=j,r=l+i;l<n;l+=(i<<1),r=l+i)
{
int temp=(1LL*a[r]*w)%MOD;
a[r]=(a[l]-temp+MOD)%MOD;
a[l]=(a[l]+temp)%MOD;
}
}
if(mode==-1)
{
int inv=PowMod(n,MOD-2);
for(int i=0;i<n;i++)
a[i]=(1LL*a[i]*inv)%MOD;
}
}
void Inv(Poly &a,Poly &i,int n)
{
static Poly temp;
if(n==1)
{
i[0]=PowMod(a[0],MOD-2);
return;
}
Inv(a,i,(n+1)/2);
int len=1;
while(len<n*2-1)
len<<=1;
copy(a,a+n,temp);
fill(temp+n,temp+len,0);
NTT(temp,len,1);
fill(i+n,i+len,0);
NTT(i,len,1);
for(int j=0;j<len;j++)
i[j]=1LL*i[j]*((2LL-1LL*temp[j]*i[j]%MOD+MOD)%MOD)%MOD;
NTT(i,len,-1);
fill(i+n,i+len,0);
}
void Mod(Poly &a,const Poly &p,int n,int m)
{
static Poly temp,p0,p1,c;
copy(a,a+n,temp);
reverse(temp,temp+n);
copy(p,p+m,p0);
reverse(p0,p0+m);
Inv(p0,p1,n-m+1);
int len=1;
while(len<(n-m+1)*2-1)
len<<=1;
fill(temp+n-m+1,temp+len,0);
NTT(temp,len,1);
fill(p1+n-m+1,p1+len,0);
NTT(p1,len,1);
for(int i=0;i<len;i++)
c[i]=(1LL*temp[i]*p1[i])%MOD;
NTT(c,len,-1);
fill(c+n-m+1,c+len,0);
reverse(c,c+n-m+1);
len=1;
while(len<n)
len<<=1;
NTT(c,len,1);
fill(p0+m,p0+len,0);
reverse(p0,p0+m);
NTT(p0,len,1);
for(int i=0;i<len;i++)
c[i]=(1LL*c[i]*p0[i])%MOD;
NTT(c,len,-1);
for(int i=0;i<n;i++)
a[i]=(a[i]-c[i]+MOD)%MOD;
}
void MulMod(Poly &a,const Poly &b,const Poly &p,int n)
{
static Poly temp;
copy(b,b+n,temp);
int len=1;
while(len<n*2)
len<<=1;
fill(a+n,a+len,0);
fill(temp+n,temp+len,0);
NTT(a,len,1);
NTT(temp,len,1);
for(int i=0;i<len;i++)
a[i]=(1LL*a[i]*temp[i])%MOD;
NTT(a,len,-1);
Mod(a,p,n*2-1,n);
}
void PowMod(Poly &res,Poly &a,long long b,const Poly &p,int n)
{
fill(res,res+n,0);
res[0]=1;
while(b)
{
if(b&1LL)
MulMod(res,a,p,n);
MulMod(a,a,p,n);
b>>=1LL;
}
}
Poly A,C,p,t,f;
int main()
{
long long N;
int K;
scanf("%d%lld",&K,&N);
for(int i=0;i<K;i++)
scanf("%d",&A[i]);
for(int i=0;i<K;i++)
scanf("%d",&C[i]);
p[K]=1;
for(int i=0;i<K;i++)
p[i]=(MOD-C[K-i-1])%MOD;
t[1]=1;
PowMod(f,t,N-1,p,K+1);
int ans=0;
for(int i=0;i<K;i++)
ans=(ans+(1LL*A[i]*f[i])%MOD)%MOD;
printf("%d\n",ans);
return 0;
}