HDU 4549 矩阵快速幂 + 快速幂取模 + 费马小定理

HDU 4549




题解: 首先能够观察到, 各项a, b的指数满足斐波那契数列, 且a得指数是b的指数的前一项。

如: f[0] = a ^ 1 * b ^ 0 

        f[ 1 ] = a ^ 0 * b ^ 1

f[2] = a ^ 1 * b ^ 1,

f[3] = a ^ 1 * b ^ 2

f[4] = a ^ 2 * b ^ 3

f[5] = a ^ 3 * b ^ 5......

poj3070里求斐波那契数列用到了费马小定理, 

对于斐波那契数列: 第n(n >= 0) 的值为矩阵(二阶方阵) 0 , 1, 1, 1的n次方矩阵的第二项即, f(n -1), f(n), f(n), f(n + 1) 对应其n次方。


所以用一个二阶方阵求其矩阵幂, 就可以得到第n项a, b的指数。

特殊的: 方阵0次方为单位矩阵, 这题也是满足的。


然后就是根据指数求快速幂了。

ps:全局都用long long , 因为这个TLE8次, 心累。。。。



code:

/*
adrui's submission
Language : C++
Result : Accepted
Love : ll
Favorite : Dragon Balls

Standing in the Hall of Fame
*/


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
#include<bitset>
#include<map>
using namespace std;

#define M(a, b) memset(a, b, sizeof(a))
#define mid ((l + r) >> 1)
#define ls rt << 1, l, mid
#define rs rt << 1|1, mid + 1, r
#define lowbit(x) (x & (-x))
#define LL long long
#define REP(n) for(int i = 0; i < n; i++)
#define debug 0
const LL  mod(1e9 + 7);

LL a, b, n;

struct Matrix {
	LL mat[2][2];														
	void init1() {															//单位矩阵
		M(mat, 0);
		for (int i = 0; i < 2; i++)
			mat[i][i] = 1;
	}
	void init2() {															//费马小定理
		mat[0][0] = 0;
		mat[0][1] = mat[1][0] = mat[1][1] = 1;
	}
};

Matrix operator * (Matrix a, Matrix b) {									//矩阵乘法
	Matrix c;	
	M(c.mat, 0);
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++)
			{
				for (int k = 0; k < 2; k++)
					c.mat[i][j] += (a.mat[i][k] * b.mat[k][j]) % (mod - 1);
				c.mat[i][j] %= (mod - 1);
			}
		}

	return c;
}

Matrix Matrix_fast_mod(LL b) {									            //快速矩阵幂
	Matrix res, tmp;
	res.init1();															//单位矩阵
	tmp.init2();

	while (b) {
		if (b & 1) res = tmp * res;
		tmp = tmp * tmp;
		b >>= 1;
	}
	return res;
}

LL fast_mod(LL ta , LL a) {													//快速幂
	LL res = 1;
	while (a) {
		if (a & 1)
			res = (res * ta) % mod;
		ta = (ta * ta) % mod;
		a >>= 1;
	}

	return res;
}

int main() {
#if debug
	freopen("in.txt", "r", stdin);
#endif //debug
	
	while (~scanf("%I64d%I64d%I64d", &a, &b, &n)) {
			Matrix tmp = Matrix_fast_mod(n);

			LL la = tmp.mat[0][0];
			LL lb = tmp.mat[0][1];

			LL ans = fast_mod(a, la) * fast_mod(b, lb) % mod;
			printf("%I64d\n", ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值