Loading

题解 : 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;
}
posted @ 2025-11-10 21:22  krsyUnalri_qwq  阅读(5)  评论(0)    收藏  举报