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

来源:互联网 发布:画图软件图标大全 编辑:程序博客网 时间:2024/05/17 00:10

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 submissionLanguage : C++Result : AcceptedLove : llFavorite : Dragon BallsStanding 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 0const 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 debugfreopen("in.txt", "r", stdin);#endif //debugwhile (~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;}


1 0