1. 程式人生 > 實用技巧 >HDU - 6755 Fibonacci Sum 二次剩餘 + 二項式定理

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(""); } }