标签:define 公式 flag its lag first ace com --
给定 \(C,\ N,\ K\)
规定 \(F_{0} = 0,\ F_{1} = 1,\ F_{n} = F_{n - 1} + F_{n - 2}\)
计算
\(1\leq N,\ C\leq 1e18,\ 1\leq K\leq 1e5\)
由斐波那契通项公式
不妨设
于是得到
由二项式定理
展开得到
交换求和顺序,整理得到
发现第二个循环内部是一个等比数列,设
由求和公式,化简第二层循环(特判 \(q = 1\))
代入原式得到
下面考虑优化计算
设
则
即
设
则 \(q,\ qn\) 可以线性递推
模意义下的指数运算要用欧拉降幂,这是一个 \(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], " \n"[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\n", ans);
}
return 0;
}
/*
3
5 1 1
2 1 2
948667308466040306 674466112463401647 84933
*/
标签:define 公式 flag its lag first ace com --
原文地址:https://www.cnblogs.com/ChenyangXu/p/13362642.html