Loading

HDU - 6755 Fibonacci Sum 二次剩余 + 二项式定理

 

 根据斐波那契数列的通项公式可以进行如下推导。

注意到后面是等比数列可以O(1)求出。还要注意的问题是 1 / sqrt(5) 在模意义下处理用二次剩余模板处理出。以及预处理组合数。

当然,直接这样写虽然复杂度上没问题但还会T

考虑以下优化:

1.由于c很大,计算A^c,B^c时用欧拉降幂减少快速幂。

2.对于公比q,发现每次都是乘a/b。维护处理,这样就不用每次都快速幂

3.求组合数预处理出阶乘的逆元

#pragma warning(disable:4996)

#include<iostream>
#include<algorithm>
//#include<bitset>
//#/include<tuple>
//#include<unordered_map>
#include<fstream>
#include<iomanip>
#include<string>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<stack>
#include<sstream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include <assert.h>
#define pb push_back
#define INF 0x3F3F3F3F
#define inf 998244353
#define moD 1000000003
#define pii pair<int,int>
#define eps 1e-6
#define equals(a,b) (fabs(a-b)<eps)
#define bug puts("bug")
#define re  register
#define fi first
#define se second
typedef  long long ll;
typedef unsigned long long ull;
const ll MOD = 1e9 + 9;
const ll Mod = 998244352;
const int maxn = 1e5 + 10;
const double Inf = 10000.0;
const double PI = acos(-1.0);
using namespace std;

ll mul(ll a, ll b, ll m) {
    ll res = 0;
    while (b) {
        if (b & 1) res = (res + a) % m;
        a = (a + a) % m;
        b >>= 1;
    }
    return res % m;
}
    
ll quickPower(ll a, ll b, ll m) {
    ll base = a;
    ll ans = 1ll;
    while (b) {
        if (b & 1) ans = mul(ans, base, m);
        base = mul(base, base, m);
        b >>= 1;
    }
    return ans;
}

ll ksm(ll a, ll b, ll m) {
    ll base = a;
    ll ans = 1ll;
    while (b) {
        if (b & 1) ans *= base, ans %= m;
        base *= base, base %= m;
        b >>= 1;
    }
    return ans;
}



ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a % b);
}

ll Lcm(ll a, ll b) {
    return a / gcd(a, b) * b;
}

int readint() {
    int x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

ll readll() {
    ll x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

ull readull() {
    ull x = 0, f = 1; char ch = getchar();
    while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

void Put(ll x) {
    if (x < 0) putchar('-'), x *= -1;
    if (x > 9) Put(x / 10);
    putchar(x % 10 + '0');
}

ll w;
struct num {
    ll x, y;
};

num mul(num a, num b, ll p)
{
    num ans = { 0,0 };
    ans.x = ((a.x * b.x % p + a.y * b.y % p * w % p) % p + p) % p;
    ans.y = ((a.x * b.y % p + a.y * b.x % p) % p + p) % p;
    return ans;
}

ll powwR(ll a, ll b, ll p) {
    ll ans = 1;
    while (b) {
        if (b & 1)ans = 1ll * ans % p * a % p;
        a = a % p * a % p;
        b >>= 1;
    }
    return ans % p;
}
ll powwi(num a, ll b, ll p) {
    num ans = { 1,0 };
    while (b) {
        if (b & 1)ans = mul(ans, a, p);
        a = mul(a, a, p);
        b >>= 1;
    }
    return ans.x % p;
}

ll solve(ll n, ll p)
{
    n %= p;
    if (p == 2)return n;
    if (powwR(n, (p - 1) / 2, p) == p - 1)return -1;//不存在
    ll a;
    while (1)
    {
        a = rand() % p;
        w = ((a * a % p - n) % p + p) % p;
        if (powwR(w, (p - 1) / 2, p) == p - 1)break;
    }
    num x = { a,1 };
    return powwi(x, (p + 1) / 2, p);
}

ll fac[maxn], inv[maxn];

ll pow_mod(ll a, ll n)
{
    ll ret = 1;
    while (n)
    {
        if (n & 1) ret = ret * a % MOD;
        a = a * a % MOD;
        n >>= 1;
    }
    return ret;
}

ll inv2 = 383008016;


void init()
{
    fac[0] = 1;
    inv[0] = inv[1] = 1;
    for (int i = 1; i < maxn - 3; i++)
    {
        fac[i] = fac[i - 1] * i % MOD;
    }
    for (int i = 2; i < maxn - 3; i++) inv[i] = ksm(fac[i], MOD - 2, MOD);
}
ll Cc(ll x, ll y)
{
    return fac[x] * inv[x - y] % MOD * inv[y] % MOD;
}




int main() {
    ll resq5 = 500000005;
    ll a = 691504013;
    ll b = 308495997;
    int T = readint();
    init();
    while (T--) {
        ll n = readll(), c = readll(), k = readll();
        ll A = ksm(a, c % (MOD - 1), MOD);
        ll B = ksm(b, c % (MOD - 1), MOD);
        ll res = ksm(276601605ll, k, MOD);
        ll ans = 0;
        ll q = ksm(B, k, MOD);
        ll invB = ksm(B, MOD - 2, MOD);
        ll change = A * invB % MOD;
        ll cc = ksm(change, (n + 1) % (MOD - 1), MOD);
        ll ini = ksm(q, (n + 1) % (MOD - 1), MOD);
        ll tmp;
        for (int i = 0; i <= k; i++) {
            if (q == 1ll) tmp = (n + 1) % MOD;
            else tmp = (-1 + MOD + ini) % MOD * ksm(q - 1, MOD - 2, MOD) % MOD;
            ans = (ans + (Cc(k, i) *  ((k - i) & 1 ? (MOD - 1) : 1)) % MOD * tmp % MOD)%MOD;
            q = q * change % MOD;
            ini = ini * cc % MOD;
        }
        res = res * ans % MOD;
        Put(res);
        puts("");
    }
}

 

posted @ 2020-08-11 17:53  MQFLLY  阅读(177)  评论(0编辑  收藏  举报