十七届同济大学程序设计预选赛-J

题目链接

十七届同济大学程序设计预选赛-J

思路

我们从这个开始考虑
F k ′ ( n ) = ∑ i = 1 n ( n − i ) k F i b ( i ) F k ′ ( n + 1 ) = ∑ i = 1 n ( n − i + 1 ) k F i b ( i ) \begin{aligned} F'_k(n)&=\sum_{i=1}^n(n-i)^kFib(i)\\ F'_k(n+1)&=\sum_{i=1}^n(n-i+1)^kFib(i)\\ \end{aligned} Fk(n)Fk(n+1)=i=1n(ni)kFib(i)=i=1n(ni+1)kFib(i)
上面两个式子做差得到
F k ′ ( n + 1 ) − F k ′ ( n ) = ∑ i = 1 n ( n − i + 1 ) k F i b ( i ) − ∑ i = I N ( n − i ) k F i b ( i ) = ∑ i = 1 n ( ( n − i ) + 1 ) k − ( n − i ) k F i b ( i ) = ∑ i = 1 n ∑ j = 0 k − 1 ( k j ) F i b ( i ) = ∑ j = 0 n ( k j ) F j ′ ( n ) \begin{aligned} &F'_k(n+1)-F'_k(n)\\ &=\sum_{i=1}^{n}(n-i+1)^kFib(i)-\sum_{i=I}^N(n-i)^kFib(i)\\ &=\sum_{i=1}^{n}((n-i)+1)^k-(n-i)^kFib(i)\\ &=\sum_{i=1}^{n}\sum_{j=0}^{k-1}\binom{k}{j}Fib(i)\\ &=\sum_{j=0}^{n}\binom{k}{j}F'_j(n)\\ \end{aligned} Fk(n+1)Fk(n)=i=1n(ni+1)kFib(i)i=IN(ni)kFib(i)=i=1n((ni)+1)k(ni)kFib(i)=i=1nj=0k1(jk)Fib(i)=j=0n(jk)Fj(n)
得到递推式子
F k ′ ( n + 1 ) = F k ′ ( n ) + ∑ j = 0 n ( k j ) F j ′ ( n ) \begin{aligned} &F'_k(n+1)=F'_k(n)+\sum_{j=0}^{n}\binom{k}{j}F'_j(n)\\ \end{aligned} Fk(n+1)=Fk(n)+j=0n(jk)Fj(n)
使用矩阵来得到所有的 F k ′ ( n ) F'_k(n) Fk(n),首先矩阵内需要有 F i b [ i ] , F i b [ i − 1 ] , F 0 ′ [ i ] , … , F k ′ [ i ] Fib[i],Fib[i-1],F'_0[i],\dots,F'_k[i] Fib[i],Fib[i1],F0[i],,Fk[i], F 0 ′ [ i ] = F [ ′ i − 1 ] + F i b [ i − 2 ] + F i b [ i − 1 ] F'_0[i]=F'_[i-1]+Fib[i-2]+Fib[i-1] F0[i]=F[i1]+Fib[i2]+Fib[i1],其他的用上面的式子推出,这样就得到一个k+3的矩阵。
得到上述的所有0~k的 F j ′ [ n ] F'_j[n] Fj[n]之后,我们来还原,
F k ′ ( n ) = ∑ i = 1 n ( n − i ) k F i b ( i ) = ∑ j = 0 k ( − 1 ) j n k − j ( k k − j ) F j ( n ) ( − 1 ) k F k ( n ) = F k ′ ( n ) − ∑ j = 0 k − 1 ( − 1 ) j n k − j ( k k − j ) F j ( n ) \begin{aligned} F'_k(n)&=\sum_{i=1}^n(n-i)^kFib(i)\\ &=\sum_{j=0}^k(-1)^jn^{k-j}\binom{k}{k-j}F_j(n)\\ (-1)^kF_k(n)&=F'_k(n)-\sum_{j=0}^{k-1}(-1)^jn^{k-j}\binom{k}{k-j}F_j(n) \end{aligned} Fk(n)(1)kFk(n)=i=1n(ni)kFib(i)=j=0k(1)jnkj(kjk)Fj(n)=Fk(n)j=0k1(1)jnkj(kjk)Fj(n)
这样就能求出 F k ( n ) F_k(n) Fk(n)了。

代码示例

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 998244353;
struct Mat{
    ll a[105][105];
    Mat(){
        memset(a,0,sizeof(a));
    }
    ll* operator[](int i){
        return a[i];
    }
};
int N = 104;
Mat operator * (Mat &a,Mat &b){
    Mat res;
    for(int i=0;i<N;i++) {
        for (int j = 0; j < N; j++) {
            for (int k = 0; k < N; k++) {
                res[i][j] += a[i][k] * b[k][j] % mod;
            }
            res[i][j] %= mod;
        }
    }
    return res;
}
ll C[505][505];
ll f_b[505],f[505],pown[505];
Mat quick_pow(Mat a,ll p){
    Mat res;
    for(int i=0;i<N;i++)res[i][i]=1;
    while(p){
        if(p&1)res=a*res;
        a=a*a;
        p>>=1;
    }
    return res;
}
void init(){
    C[0][0]=1;
    for(int i=0;i<=500;i++){
        for(int j=0;j<=i;j++){
            C[i+1][j]+=C[i][j];
            C[i+1][j+1]+=C[i][j];
            C[i][j]%=mod;
            C[i+1][j+1]%=mod;
        }
    }
}
int main(){
    ll n,k;
    cin>>n>>k;
    init();
    pown[0]=1;
    for(int i=1;i<=k;i++){
        pown[i]=pown[i-1]*(n%mod)%mod;
    }
    N = k + 3;
    Mat a;
    a[0][0]=1;
    a[0][1]=1;
    a[1][0]=1;
    a[2][2]=1;
    a[2][0]=1;
    a[2][1]=1;//对应前三项斐波那契以及F'[0]
    for(int i=1;i<=k;i++){
        for(int j=0;j<=i;j++){
            a[i+2][j+2]=C[i][j];//对应后面的0~k
        }
    }
    a=quick_pow(a,n);
    for(int i=0;i<=k;i++){
        f_b[i]=a[i+2][1];
    }
    f[0]=f_b[0];
    for(int i=1;i<=k;i++)//转换
    {
        ll fi = f_b[i];
        ll flag = 1;
        for(int j=0;j<i;j++){
            flag = mod - flag;
            fi+=flag*C[i][j]%mod*pown[i-j]%mod*f[j]%mod;
        }
        fi%=mod;
        fi*=flag;
        f[i]=fi%mod;
    }
    cout<<f[k]<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值