2013长沙市邀请赛 HDU 4565 So Easy!(矩阵快速幂)

2013长沙邀请赛 HDU 4565 So Easy!(矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4565

矩阵快速幂,要推公式。

参考了网上的题解,简直屌

    2013长沙市邀请赛 HDU 4565 So Easy!(矩阵快速幂)

代码:

#include <stdio.h>
#include <string.h>
#include <math.h>

long long a, b, n, m;

struct mat {
    long long v[2][2];
    mat() {
	memset(v, 0, sizeof(v));
    }
    mat operator * (mat a) {
	mat c;
	for (int i = 0; i < 2; i++)
	    for (int j = 0; j < 2; j++)
		for (int k = 0; k < 2; k++) {
		    c.v[i][j] = ((c.v[i][j] + v[i][k] * a.v[k][j]) % m + m) % m;
		}
	return c;
    }
};

mat pow_mod(mat a, long long k) {
    if (k <= 1) return a;
    mat ans = pow_mod(a * a, k / 2); 
    if (k&1) ans = ans * a;
    return ans;
}

int main() {
    while (~scanf("%lld%lld%lld%lld", &a, &b, &n, &m)) {
	mat s;
	s.v[0][0] = 2 * a; s.v[0][1] = -(a * a - b);
	s.v[1][0] = 1; s.v[1][1] = 0;
	long long c1 = (long long)(ceil(a + sqrt(b))) % m;
	long long c2 = (long long)(ceil((a + sqrt(b)) * (a + sqrt(b)))) % m;
	if (n == 1) printf("%lld\n", c1);
	else if (n == 2) printf("%lld\n", c2);
	else {
	    mat ans = pow_mod(s, n - 2);
	    printf("%lld\n", (((((ans.v[0][0] * c2 % m) + m) % m) + (((ans.v[0][1] * c1 % m) + m) % m)) + m) % m);
	}
    }
    return 0;
}