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