题解 : P14461
数学题。
记多项式系数向量为 \(a=(a_1,a_2,...,a_m)\)。定义线性算子 \(D\) 作用在某系数向量上为 \((D \cdot a)_i=(i+1)a_{i+1}\),\(0 \le i \le m\)。
题目给定递推:
\[\begin{cases}
F_i(x)=G_{i-1}(x)+G^{\prime}_{i-1}(x) \\ \\
G_i(x)=F_{i-1}(X)-F^{\prime}_{i-1}(x)
\end{cases}
\]
用恒等算子 \(I\) 和 \(D\) 表示为向量形式:
\[F_i=(I+D)G_{i-1}
\]
\[G_i=(I-D)F_{i-1}
\]
化简:
\[F_i=(I+D)G_{i-1}=(I+D)(I-D)F_{i-1}=(I-D)^2F_{i-1}
\]
\[G_i=(I-D)F_{i-1}=(I-D)(I+D)G_{i-1}=(I-D)^2G_{i-1}
\]
因此该递推式就是作用算子 \(S=(I-D)^2\)。
设 \(k=\lfloor \frac{n}{2} \rfloor\),则:
若 \(n\) 为偶数:
\[F_i=S^k \cdot F_0
\]
\[G_i=S^k \cdot G_0
\]
若 \(n\) 为奇数:
\[F_i=(I+D) \cdot S^k \cdot G_0
\]
\[G_i=(I-D) \cdot S^k \cdot F_0
\]
因此问题转化为如何高效计算 \(S^k=(I-D^2)^k\) 在系数向量上的作用。
我们利用二项式展开:
\[S^k=(I-D^2)^k=\sum\limits_{t=0}^{k} {k\choose t} \cdot (-1)^t \cdot D^{2t}
\]
对于某一初始向量 \(a\),第 \(i\) 个系数为:
\[(S^ka)_i=\sum\limits_{t\ge 0} {k\choose t} \cdot (-1)^t \cdot (D^{2t}a)_i
\]
把 \(D^{2t}\) 的作用写成系数形式:
\[(D^{2t}a)_i=(i+1)(i+2) \cdots (i+2t) \cdot a_{i+2t}=\frac{(i+2t)!}{i!} \cdot a_{i+2t}
\]
因此得到显式公式:
\[(S^ka)_i=\sum\limits_{t=0}^{\lfloor \frac{m-i}{2} \rfloor} {k\choose t} \cdot \frac{(i+2t)!}{i!} \cdot a_{i+2t}
\]
当 \(n\) 为奇数时,再做一次 \(I\pm D\) 即可。
AC代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
const int N=5010;
int f0[N],g0[N];
int frc[N],inv[N];
int c[N];
int fk[N],gk[N],fn[N],gn[N];
int qkp(int a,int b){
int s=1;
while(b){
if(b&1) s=s*a%mod;
a=a*a%mod,b>>=1;
}
return s;
}
void ask(int *a,int *b,int m){
for(int i=0;i<=m;++i) b[i]=0;
for(int i=0;i<=m;++i){
int lim=(m-i)/2;
for(int t=0;t<=lim;t++){
int x=c[t];
if(t&1) x=(mod-x)%mod;
int p=frc[i+2*t]*inv[i]%mod;
b[i]=(b[i]+x*p%mod*a[i+2*t])%mod;
}
}
}
int n,m;
void init(int m){
frc[0]=1;
for(int i=1;i<=m;i++) frc[i]=frc[i-1]*i%mod;
inv[m]=qkp(frc[m],mod-2);
for(int i=m;i>0;i--) inv[i-1]=inv[i]*i%mod;
}
signed main(){
cin.tie(0)->sync_with_stdio(0);
cin>>n>>m;
init(m);
for(int i=0;i<=m;++i) cin>>f0[i],f0[i]%=mod;
for(int i=0;i<=m;++i) cin>>g0[i],g0[i]%=mod;
int k=n/2;
c[0]=1;
int km=(k%mod+mod)%mod,num=1;
for(int t=1;t<=m/2;++t){
int f=(km-(t-1))%mod;
if(f<0) f+=mod;
num=num*f%mod;
c[t]=num*inv[t]%mod;
}
ask(f0,fk,m);
ask(g0,gk,m);
if(n&1){
for(int i=0;i<=m;++i){
int a=gk[i],b=0;
if(i+1<=m) b=(i+1)*gk[i+1]%mod;
fn[i]=(a+b)%mod;
int c=fk[i],d=0;
if(i+1<=m) d=(i+1)*fk[i+1]%mod;
gn[i]=(c-d)%mod;
if(gn[i]<0) gn[i]+=mod;
}
}
else{
for(int i=0;i<=m;++i) fn[i]=fk[i],gn[i]=gk[i];
}
for(int i=0;i<=m;++i){
cout<<(fn[i]%mod+mod)%mod<<" ";
}
cout<<"\n";
for(int i=0;i<=m;++i){
cout<<(gn[i]%mod+mod)%mod<<" ";
}
cout<<"\n";
return 0;
}

浙公网安备 33010602011771号