1. 程式人生 > >【hdu4549 M斐波那契數列】【矩陣快速冪】【F[n] = F[n-1] * F[n-2] ,求F[n] 】

【hdu4549 M斐波那契數列】【矩陣快速冪】【F[n] = F[n-1] * F[n-2] ,求F[n] 】

【連結】

【題意】

F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 給出a, b, n,求出F[n]

【分析】

寫出幾項後,發現:F[n]=a^x*b^y,x,y成斐波那契數列。

且有規律:ans=a^(F[n-1])*b^(F[n])

斐波那契數列F[]陣列可通過矩陣快速冪n^3logk求解,但是由於n很大,繼續直接求解會超時。

由費馬小定理a^(p-1)+1==0(mod p).繼續求解時可以簡化冪上(p-1)得迴圈節。

【程式碼】

#include<bits./stdc++.h>
using namespace std;
using ll = long long;

const int maxn = 1000006;
const int mod = 1e9 + 7;
ll F[maxn];
ll a, b, n;

ll qpow2(ll a, ll b) {
	ll res = 1;
	ll ans = a % (mod);
	while (b) {
		if (b & 1) 
			res = res * ans%(mod);
		ans = ans * ans%(mod);
		b >>= 1;
	}
	return res;
}

struct ma {
	ll m[2][2];
};

ma mul(ma a, ma b) {
	ma c;
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 2; j++) {
			c.m[i][j] = 0;
			for (int k = 0; k < 2; k++) {
				c.m[i][j] += (a.m[i][k] * b.m[k][j]) % (mod-1);
			}
			c.m[i][j] %= (mod-1);
		}
	}
	return c;
}

ma qpow1(ma a, ll n) {
	ma ans = { 1,0,0,1 };
	ma res = a;
	while (n) {
		if (n & 1)ans = mul(ans, res);
		res = mul(res, res);
		n >>= 1;
	}
	return ans;
}

int main() {
	ma tmp = { 0,1,1,1 };
	while (~scanf("%lld%lld%lld", &a, &b, &n)) {
		ma p = qpow1(tmp, n);
		printf("%lld\n", qpow2(a, p.m[0][0])*qpow2(b, p.m[0][1]) % mod);
	}
}