$HDU 2020$ 多校第一场

(6755 Fibonacci Sum)

题意

给定 (C, N, K)

规定 (F_{0} = 0, F_{1} = 1, F_{n} = F_{n - 1} + F_{n - 2})

计算

[F_{0}^k + F_{C}^k + F_{2C}^k + ... + F_{CN}^k ]

(1leq N, Cleq 1e18, 1leq Kleq 1e5)

题解

由斐波那契通项公式

[F_{n} = frac{1}{sqrt{5}}((frac{1 + sqrt{5}}{2})^n - (frac{1 - sqrt{5}}{2})^{n}) ]

不妨设

[a = frac{1 + sqrt{5}}{2}, b = frac{1 - sqrt{5}}{2} ]

于是得到

[sum_{i = 0}^{N}F_{ic}^k = sum_{i = 0}^{N}(frac{1}{sqrt{5}})^{k}(a^{ic} - b^{ic})^{k} ]

由二项式定理

[(a + b)^n = sum_{i = 0}^{n}C_{n}^{i}a^{n - i}b^{i} ]

展开得到

[sum_{i = 0}^{N}F_{ic}^k = (frac{1}{sqrt{5}})^{k}sum_{i = 0}^{N}sum_{j = 0}^{k}C_{k}^{j}(a^{ic})^{k - j}(-b^{ic})^{j} ]

交换求和顺序,整理得到

[sum_{i = 0}^{N}F_{ic}^k = (frac{1}{sqrt{5}})^{k}sum_{j = 0}^{k}C_{k}^{j}(-1)^{j}sum_{i = 0}^{N}(a^{c(k - j)}cdot b^{cj})^{i} ]

发现第二个循环内部是一个等比数列,设

[q = a^{c(k - j)}cdot b^{cj} = left[a^{k - j}b^{j} ight]^{c} ]

由求和公式,化简第二层循环(特判 (q = 1)

[sum_{i = 0}^{N}(a^{c(k - j)}cdot b^{cj})^{i} = frac{1 - q^{N + 1}}{1 - q} ]

代入原式得到

[sum_{i = 0}^{N}F_{ic}^k = (frac{1}{sqrt{5}})^{k}sum_{j = 0}^{k}C_{k}^{j}(-1)^{j}(frac{q^{N + 1} - 1}{q - 1}) ]

下面考虑优化计算

[q_{j} = left[a^{k - j}b^{j} ight]^{c}, qn_{j} = left[a^{k - j}b^{j} ight]^{c cdot (N + 1)} ]

[q_{j + 1} = left[a^{k - j - 1}b^{j + 1} ight]^{c}, qn_{j + 1} = left[a^{k - j - 1}b^{j + 1} ight]^{c cdot (N + 1)} ]

[q_{j + 1} = frac{q_{j}}{a^{c}}cdot b^{c}, qn_{j + 1} = frac{qn_{j}}{a^{ccdot (N + 1)}}cdot b^{ccdot (N + 1)} ]

[K_{1} = frac{b^c}{a^c}, K_{2} = frac{b^{ccdot (N + 1)}}{a^{ccdot (N + 1)}} ]

(q, qn) 可以线性递推

[q_{j + 1} = q_{j}cdot K_{1}, qn_{j + 1} = qn_{j}cdot K_{2} ]

模意义下的指数运算要用欧拉降幂,这是一个 (wa)

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define pb push_back
#define dbg(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " 
"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL MOD = 1e9 + 9;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MAXN = 1e5 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;

LL qpow(LL a, LL b)
{
    b %= MOD - 1;
    if(!a) return 0;
    LL ans = 1;
    while(b) {
        if(b & 1) ans *= a, ans %= MOD;
        a *= a, a %= MOD, b >>= 1;
    }
    return ans;
}
LL getInv(LL x) {return qpow(x, MOD - 2);}
LL Add(LL a, LL b) {a = (a % MOD + MOD) % MOD; b = (b % MOD + MOD) % MOD; return (a + b) % MOD;}
LL Sub(LL a, LL b) {a = (a % MOD + MOD) % MOD; b = (b % MOD + MOD) % MOD; return (a - b + MOD) % MOD;}
LL Mul(LL a, LL b) {a = (a % MOD + MOD) % MOD; b = (b % MOD + MOD) % MOD; return a * b % MOD;}
LL Div(LL a, LL b) {a = (a % MOD + MOD) % MOD; b = (b % MOD + MOD) % MOD; return b * getInv(a) % MOD;}

int t, K;
LL N, C, fac[MAXN], inv_fac[MAXN], q[MAXN], qn[MAXN];
const LL A = 383008016, B = getInv(2), INVA = getInv(A);
const LL a = Mul(Add(1, A), B), b = Mul(Sub(1, A), B);

void ini()
{
    fac[0] = 1;
    for(int i = 1; i < MAXN; ++i) fac[i] = Mul(fac[i - 1], i);
    inv_fac[MAXN - 1] = getInv(fac[MAXN - 1]);
    for(int i = MAXN - 2; i >= 0; --i) inv_fac[i] = Mul(inv_fac[i + 1], i + 1);
}
LL getC(int k, int i)
{
    return Mul(fac[k], Mul(inv_fac[i], inv_fac[k - i]));
}
LL getGeoSum(LL Q, LL Qn)
{
    LL res = Div(Sub(Q, 1), Sub(Qn, 1));
    return res;
}
int main()
{
    ini();
    scanf("%d", &t);
    while(t--) {
        scanf("%lld %lld %d", &N, &C, &K);
        LL ans = 0;
        LL K1 = Div(qpow(a, C), qpow(b, C));
        LL K2 = Div(qpow(qpow(a, C), N + 1), qpow(qpow(b, C), N + 1));
        q[0] = qpow(qpow(a, K), C);
        qn[0] = qpow(q[0], N + 1);
        for(int j = 1; j <= K; ++j) {
            q[j] = Mul(q[j - 1], K1);
            qn[j] = Mul(qn[j - 1], K2);
        }
        for(int j = 0; j <= K; ++j) {
            LL Q = q[j], Qn = qn[j];
            LL Com = getC(K, j);
            LL flag = j % 2 ? -1 : 1;
            LL sum1 = Mul(Com, flag), sum2 = 0;
            if(Q == 1) sum2 = Mul(sum1, Add(N, 1));
            else sum2 = Mul(sum1, getGeoSum(Q, Qn));
            ans = Add(ans, sum2);
        }
        LL co = qpow(INVA, K);
        ans = Mul(ans, co);
        printf("%lld
", ans);
    }
    return 0;
}
/*
3
5 1 1
2 1 2
948667308466040306 674466112463401647 84933
*/
原文地址:https://www.cnblogs.com/ChenyangXu/p/13362642.html