2020 杭电多校 #1

E - Fibonacci Sum HDU - 6755

解题思路:
2020 杭电多校 #1_第1张图片
二项式展开:
2020 杭电多校 #1_第2张图片
AC代码:

#include 
using namespace std;
typedef long long ll;
const ll Mod = 1000000009;
const ll M = 616991993;
const int Maxk = 100005;
ll N, C, K, T;
ll num[Maxk];
void Cal_Num() {
	num[0] = 1;
	for (int i = 1; i < Maxk; i++) num[i] = num[i - 1] * i % Mod;
}
inline ll q_pow(ll a, ll b) {
	ll res = 1;
	a %= Mod;
	while (b) {
		if (b & 1) res = res * a % Mod;
		a = a * a % Mod;
		b >>= 1;
	}
	return res % Mod;
}
int main() {
	scanf("%lld", &T);
	Cal_Num();
	//根据二次剩余定理,求出根号五的同模,然后替换 
	ll d = q_pow(M, Mod - 2), a = (1 + M) / 2, b = (1 - M) / 2;//d, a, b是不会变化的 
	while (T--) {
		ll sum = 0;
		scanf("%lld%lld%lld", &N, &C, &K);
		ll ne;
		
        ll da = q_pow(a, -C % (Mod - 1) + Mod - 1), db = q_pow(b, C); 
        ll dab = da * db % Mod;//二项式后一项与前一项公比为a^(-C) * b^C(不考虑组合数) 
        ll qdab = q_pow(dab, N + 1);//对二项式每一项求和后,前一项与后一项比为 (a^(-C) * b^C) ^(N + 1) 
        
		ll q = (q_pow(q_pow(a, K), C) % Mod + Mod) % Mod, qn = q_pow(q, N + 1);//因为第一项为(a^(C * K))^i 
		for (int j = 0; j <= K; j++) {//二项式展开,从第一项开始 
			ll x = q_pow(num[j] * num[K - j] % Mod, Mod - 2);//求组合数 
			if (j & 1) ne = -1;
			else ne = 1;
			if (q == 1) sum = (sum + ne * x * num[K] % Mod * ((N + 1) % Mod) + Mod) % Mod; 
			else sum = (sum + ne * x * num[K] % Mod * (qn - 1) % Mod * q_pow(q - 1, Mod - 2) % Mod + Mod) % Mod;
			// (qn - 1) * q_pow(q - 1, Mod - 2) 等比数列求和公式 
			q = q * dab % Mod;
            qn = qn * qdab % Mod;
		}
		sum = (q_pow(d, K) * sum + Mod) % Mod; 
		printf("%lld\n", sum);
	}
}
/*
1
81283237295399823 62 24
*/

你可能感兴趣的:(杭电多校)