【训练题36:数学】斐波那契各项幂次前缀和 | ZOJ 3774

【训练题36:数学】斐波那契各项幂次前缀和

正题

  • 【链接】
    斐波那契各项幂次前缀和
  • 【题意】给定 n , K n,K n,K,求出:
    ∑ i = 1 n ( F i b i ) K ( m o d 1 e 9 + 9 ) \sum_{i=1}^n (Fib_i)^{K}\pmod {1e9+9} i=1n(Fibi)K(mod1e9+9)
    其中 F i b i Fib_i Fibi 表示第 i i i 个斐波那契数字, F i b [ ] = [ 1 , 1 , 2 , 3 , 5 , 8 , ⋯   ] Fib[]=[1,1,2,3,5,8,\cdots] Fib[]=[1,1,2,3,5,8,]
  • 【范围】
    1 ≤ n ≤ 1 0 18 1\le n\le 10^{18} 1n1018
    1 ≤ K ≤ 1 0 5 1\le K\le 10^5 1K105

解法

  • 由于 K K K 比较大,我们不能直接用矩阵快速幂去做。考虑斐波那契数字的显式公式
    具体内容见我的博客:【小组专题三:斐波那契专题】
    f n = 1 5 ( α n − β n ) f_n=\frac{1}{\sqrt 5}(\alpha^n-\beta^n) fn=5 1(αnβn)
    其中 α = 5 + 1 2 , β = 5 − 1 2 \alpha=\frac{\sqrt5+1}{2},\beta=\frac{\sqrt5-1}{2} α=25 +1,β=25 1
    于是,我们要求的内容就变成了:(以下式子皆省略模数)
    ∑ i = 1 n ( F i b i ) K = ∑ i = 1 n 1 5 K ( α i − β i ) K = 1 5 K ∑ i = 1 n ( α i − β i ) K \sum_{i=1}^n (Fib_i)^{K}=\sum_{i=1}^n \frac{1}{\sqrt5^K}(\alpha^i-\beta^i)^K= \frac{1}{\sqrt5^K}\sum_{i=1}^n(\alpha^i-\beta^i)^K i=1n(Fibi)K=i=1n5 K1(αiβi)K=5 K1i=1n(αiβi)K
    1 5 K = R e \frac{1}{\sqrt5^K}=Re 5 K1=Re
    我们只要求后面的一个二项式即可。我们把二项式拆开来,得到:
    F i b n = R e ( ( − 1 ) 0 C K 0 α K n β 0 n + ( − 1 ) 1 C K 1 α ( K − 1 ) n β 1 ⋅ n + ⋯ ) Fib_n=Re\Big( (-1)^0C_K^0 \alpha^{Kn}\beta^{0n} + (-1)^1C_K^1 \alpha^{(K-1)n}\beta^{1\cdot n} +\cdots\Big) Fibn=Re((1)0CK0αKnβ0n+(1)1CK1α(K1)nβ1n+)
    考虑到第 i i i 项,即系数为 ( − 1 ) i C K i α ( K − i ) n β i ⋅ n (-1)^iC_K^i\alpha^{(K-i)n}\beta^{i\cdot n} (1)iCKiα(Ki)nβin
    考虑到每一个 n n n,该项成等比数列,即:公比为 α ( K − i ) β i \alpha^{(K-i)}\beta^i α(Ki)βi,用等比公式求出即可。

问题一 :根号五?

  • 【Q】考虑到需要多次计算出 5 \sqrt5 5 的值,在取模意义下怎么得到?
  • 【A】就是二次剩余的知识,见我的博客 【算法讲18:二次剩余】
    c i p o l l a cipolla cipolla 即可预处理算出该模意义下的 5 \sqrt5 5 的值。

问题二 :公比模意义为一?

  • 【Q】根据等比求和,公比必须不为 1 1 1。但是 α ( K − i ) β i \alpha^{(K-i)}\beta^i α(Ki)βi 在取模意义下可能为 1 1 1 咋办?
  • 【A】如果公比为 1 1 1,那么每一项取模意义下值都是第一项。贡献为 R e × ( − 1 ) i × n Re\times (-1)^i\times n Re×(1)i×n

核心代码

  • 时间复杂度: O ( K log ⁡ K ) O(K\log K) O(KlogK)
/*
 _            __   __          _          _
| |           \ \ / /         | |        (_)
| |__  _   _   \ V /__ _ _ __ | |     ___ _
| '_ \| | | |   \ // _` | '_ \| |    / _ \ |
| |_) | |_| |   | | (_| | | | | |___|  __/ |
|_.__/ \__, |   \_/\__,_|_| |_\_____/\___|_|
        __/ |
       |___/
*/
const ll sq5 = 383008016;
const ll iv2 = inv(2);
ll fac[MAX],ivfac[MAX];
ll C(int n,int m){
    if(m < 0 || m > n)return 0;
    return fac[n] * ivfac[m] % MOD * ivfac[n - m] % MOD;
}
void init(int n){
    fac[0] = 1;
    for(int i = 1;i <= n;++i){
        fac[i] = fac[i-1] * i % MOD;
    }
    ivfac[n] = inv(fac[n]);
    for(int i = n - 1;i >= 0;--i){
        ivfac[i] = ivfac[i+1] * (i + 1) % MOD;
    }
}
int main()
{
    init((int)1e5);
    int T;scanf("%d",&T);
    while(T--){
        ll n,k;
        scanf("%lld%lld",&n,&k);
        ll xi = inv(qpow(sq5,k));
        ll alpha = (1LL + sq5) * iv2 % MOD;
        ll beta  = (1LL - sq5 + MOD) * iv2 % MOD;
        ll res = 0;
        for(int i = 0;i <= k;++i){
            ll tmp = C(k,i);
            if(i & 1)tmp = (-tmp + MOD) % MOD;

            ll shu = qpow(alpha,k-i) * qpow(beta,i) % MOD;
            ll shu2= qpow(shu,n);
            if(shu == 1){		/// 公比为 1
                res = (res + n % MOD * tmp % MOD) % MOD;
                continue;
            }					/// 等比数列求和公式
            tmp = tmp * shu % MOD * (shu2 - 1) % MOD * inv(shu - 1) % MOD;
            res = (res + tmp) % MOD;
        }
        res = res * xi % MOD;
        res = (res + MOD) % MOD;
        printf("%lld\n",res);

    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值