2019牛客暑期多校训练营(第九场)A.The power of Fibonacci(Fibonomial coefficients+常系数线性递推)

本文介绍了一种高效求解斐波那契数列幂次求和问题的方法,利用循环节和Fibonomial coefficients的概念,通过常系数线性递推和矩阵快速幂优化算法,解决了大范围内的求和问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

{ f 0 = 0 f 1 = 1 f n = f n − 1 + f n − 2 , n ≥ 2 \left\{\begin{matrix} f_0=0\\ f_1=1\\ f_n=f_{n-1}+f_{n-2},n\geq 2 \end{matrix}\right. f0=0f1=1fn=fn1+fn2,n2
给你 n n n m m m
∑ i = 0 n f i m   % 1000000000 \sum_{i=0}^{n}f_{i}^m \ \% 1000000000 i=0nfim %1000000000
1 ≤ n ≤ 1 0 9 , 1 ≤ m ≤ 1000 1\leq n\leq 10^9,1\leq m \leq 1000 1n109,1m1000

思路

介绍了循环节的做法
现在我们用官方题解的方法来做这道题
已知
f n = f n − 1 + f n − 2 f_{n}=f_{n-1}+f_{n-2} fn=fn1+fn2
f n − f n − 1 − f n − 2 = 0 f_{n}-f_{n-1}-f_{n-2}=0 fnfn1fn2=0
二次幂下的斐波那契的递推式为
f n 2 − 2 f n − 1 2 − 2 f n − 2 2 + f n − 3 2 = 0 f_{n}^2-2f_{n-1}^2-2f_{n-2}^2+f_{n-3}^2=0 fn22fn122fn22+fn32=0
三次幂
f n 3 − 3 f n − 1 3 − 6 f n − 2 3 + 3 f n − 3 3 + f n − 4 3 = 0 f_{n}^3-3f_{n-1}^3-6f_{n-2}^3+3f_{n-3}^3+f_{n-4}^3=0 fn33fn136fn23+3fn33+fn43=0
这个次幂的递推式前面的系数是什么呢。
这个系数的绝对值就是Fibonomial coefficients
这个Fibonomial coefficients是什么呢
我们知道二项式系数有
C n m = n ( n − 1 ) ( n − 2 ) ( n − 3 ) ⋯ ( n − m + 1 ) 1 ∗ 2 ∗ 3 ∗ ⋯ ∗ m C_{n}^{m}=\frac{n(n-1)(n-2)(n-3)\cdots(n-m+1)}{1*2*3*\cdots*m} Cnm=123mn(n1)(n2)(n3)(nm+1)
而这个Fibonomial coefficients就是类似于二项式系数的方法只是把数的乘积改为斐波那契数的乘积了

A n m = f n ∗ f n − 1 ∗ f n − 2 ∗ ⋯ ∗ f n − m + 1 f 1 ∗ f 2 ∗ f 3 ∗ ⋯ ∗ f m A_{n}^m=\frac{f_{n}*f_{n-1}*f_{n-2}*\cdots*f_{n-m+1}}{f_{1}*f_{2}*f_{3}*\cdots*f_{m}} Anm=f1f2f3fmfnfn1fn2fnm+1
打个表出来就是
n ∖ m 0 1 2 3 4 5 6 7 0 : 1 1 : 1 1 2 : 1 1 1 3 : 1 2 2 1 4 : 1 3 6 3 1 5 : 1 5 15 15 5 1 6 : 1 8 40 60 40 8 1 7 : 1 13 104 260 260 104 13 1 \begin{matrix} n \setminus m & 0 &1 &2 &3 &4 &5&6&7\\ 0: & 1 \\ 1: & 1 &1 \\ 2: & 1& 1 &1 \\ 3:& 1 & 2 & 2 & 1 \\ 4: & 1 & 3 & 6 & 3 &1 \\ 5:& 1& 5 & 15 & 15 & 5 &1 \\ 6:&1&8&40&60&40&8&1\\ 7:&1&13&104&260&260&104&13&1 \end{matrix} nm0:1:2:3:4:5:6:7:01111111111123581321261540104313156026041540260518104611371
结合到原题上会发现如果要求的是 k k k次幂的求和,那么递推式全移到左边所有系数的绝对值就是这里的 k + 1 k+1 k+1
根据 o e i s oeis oeis中的公式这个Fibonomial coefficients有如下的递推公式
A n k = f n − k − 1 ∗ A n − 1 k − 1 + f k + 1 ∗ A n − 1 k A_{n}^{k}=f_{n-k-1}*A_{n-1}^{k-1}+f_{k+1}*A_{n-1}^k Ank=fnk1An1k1+fk+1An1k和杨辉三角的递推公式差不多
但是这里是绝对值的系数。我们要的是有符号的系数那就是 Signed Fibonomial triangle
根据 o e i s oeis oeis中的说法有
A n m = ( − 1 ) ⌊ m + 1 2 ⌋ A n m A_{n}^{m}=(-1)^{\left \lfloor \frac{m+1}{2} \right \rfloor}A_{n}^{m} Anm=(1)2m+1Anm
那么我们可以打表得到斐波那契数列 m m m次的递推式的系数即
A m + 1 0 f n m + A m + 1 1 f n − 1 m + A m + 1 2 f n − 2 m + ⋯ + A m + 1 m + 1 f n − m − 1 m = 0 A_{m+1}^{0}f_n^{m}+A_{m+1}^{1}f_{n-1}^m+A_{m+1}^{2}f_{n-2}^m+\cdots+A_{m+1}^{m+1}f_{n-m-1}^m=0 Am+10fnm+Am+11fn1m+Am+12fn2m++Am+1m+1fnm1m=0
有了递推式后,我们最后要求的是和而不是 f n m f_{n}^m fnm,那怎么求解呢。这个时候就有一个技巧了,为了容易表示我们把原式变成
a 0 f n + a 1 f n − 1 + a 2 f n − 2 + ⋯ + a m + 1 f n − m − 1 = 0 a_0f_n+a_1f_{n-1}+a_2f_{n-2}+\cdots+a_{m+1}f_{n-m-1}=0 a0fn+a1fn1+a2fn2++am+1fnm1=0
已知 a 0 a_0 a0恒为 1 1 1
f n = − ( a 1 f n − 1 + a 2 f n − 2 + ⋯ + a m + 1 f n − m − 1 ) f_n=-(a_1f_{n-1}+a_2f_{n-2}+\cdots+a_{m+1}f_{n-m-1}) fn=(a1fn1+a2fn2++am+1fnm1)
又有 f n = S n − S n − 1 f_n=S_n-S_{n-1} fn=SnSn1,其中 S n = ∑ i = 1 n f i S_{n}=\sum_{i=1}^nf_i Sn=i=1nfi,可以将这条式子带入有
S n − S n − 1 = − ( a 1 ( S n − 1 − S n − 2 ) + a 2 ( S n − 2 − S n − 3 ) + ⋯ + a m + 1 ( S n − m − 1 − S n − m − 2 ) ) S_n-S_{n-1}=-(a_1(S_{n-1}-S_{n-2})+a_2(S_{n-2}-S_{n-3})+\cdots+a_{m+1}(S_{n-m-1}-S_{n-m-2})) SnSn1=(a1(Sn1Sn2)+a2(Sn2Sn3)++am+1(Snm1Snm2))
整理有
S n = ( 1 − a 1 ) S n − 1 + ( a 1 − a 2 ) S n − 2 + ( a 2 − a 3 ) S n − 3 + ⋯ + ( a m − a m + 1 ) S n − m − 1 + a m + 1 S n − m − 2 S_n=(1-a_1)S_{n-1}+(a_1-a_2)S_{n-2}+(a_2-a_3)S_{n-3}+\cdots+(a_{m}-a_{m+1})S_{n-m-1}+a_{m+1}S_{n-m-2} Sn=(1a1)Sn1+(a1a2)Sn2+(a2a3)Sn3++(amam+1)Snm1+am+1Snm2
这就是一个常系数线性递推了,由于 m ≤ 1000 m\leq 1000 m1000,所以矩阵快速幂就不行了,我们用优化的 O ( m 2 l o g ( n ) ) O(m^2log(n)) O(m2log(n))的常系数线性递推的板子就可以了

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e3+5;
const int mod=1000000000;
int n,m,a[N],h[N],c[N],b[N],tmp[N<<1];
long long A[N][N];
long long f[N];
void get_A()
{
    f[0]=0;
    f[1]=1;
    for(int i=2; i<N; i++)
        f[i]=(f[i-1]+f[i-2])%mod;
    for(int i=0; i<N; i++)
        A[i][0]=A[i][i]=1;
    for(int i=1; i<N; i++)
    {
        for(int j=1; j<i; j++)
        {
            A[i][j]=(f[i-j-1]*A[i-1][j-1]%mod+f[j+1]*A[i-1][j]%mod)%mod;
        }
    }
    for(int i=0; i<N; i++)
    {
        for(int j=0; j<=i; j++)
        {
            if(((j+1)/2)%2)
                A[i][j]=-A[i][j];
        }
    }
}
void mul(int *a1,int *a2)
{
    for(int i=0; i<=2*m; i++)tmp[i]=0;
    for(int i=0; i<=m; i++)
    {
        for(int j=0; j<=m; j++)
        {
            tmp[i+j]=(tmp[i+j]+1ll*a1[i]*a2[j])%mod;
        }
    }
    for(int i=2*m-2; i>=m; i--)
    {
        for(int j=0; j<m; j++)
        {
            tmp[i-m+j]=(tmp[i-m+j]+1LL*tmp[i]*a[m-j])%mod;
        }
        tmp[i]=0;
    }
    for(int i=0; i<m; i++)a1[i]=tmp[i];
}
void pow(int *a1,int t,int *a2)
{
    for(; t; t>>=1)
    {
        if(t&1)mul(a2,a1);
        mul(a1,a1);
    }
}
long long quickmod(long long a,long long b)
{
    long long ans=1;
    while(b)
    {
        if(b&1)
            ans=ans*a%mod;
        a=a*a%mod;
        b=b>>1;
    }
    return ans;
}
int main()
{
    get_A();
    scanf("%d%d",&n,&m);
    a[1] = 1;
    for (int i = 1; i <= m + 1; i++)
    {
        a[i]=(a[i]-A[m+1][i]+mod)%mod;
        a[i+1]=(a[i+1]+A[m+1][i]+mod)%mod;
    }
    for(int i=1;i<=m+5;i++)
        f[i]=(f[i-1]+quickmod(f[i],m))%mod;
    if(n<m)
    {
        printf("%d\n",f[n]);
        return 0;
    }
    m+=2;
    b[1]=1;
    c[0]=1;
    pow(b,n,c);
    int ans=0;
    for(int i=0; i<m; i++)
    {
        ans=(ans+1LL*c[i]*f[i]%mod+mod)%mod;
    }
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值