【hdu4549 M斐波那契数列】【矩阵快速幂】【F[n] = F[n-1] * F[n-2] ,求F[n] 】

【链接】

http://acm.hdu.edu.cn/showproblem.php?pid=4549

【题意】

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

猜你喜欢

转载自blog.csdn.net/running_acmer/article/details/82937782