LOJ1070(SummerTrainingDay05-B 矩阵快速幂)
Algebraic Problem
Given the value of a+b and ab you will have to find the value of an+bn. a and bnot necessarily have to be real numbers.
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.
Each case contains three non-negative integers, p, q and n. Here p denotes the value of a+b and q denotes the value of ab. Each number in the input file fits in a signed 32-bit integer. There will be no such input so that you have to find the value of 00.
Output
For each test case, print the case number and (an+bn) modulo 264.
Sample Input
2
10 16 2
7 12 3
Sample Output
Case 1: 68
Case 2: 91
令Sn = an+bn ,则有递推公式Sn = p×Sn-1 - q×Sn-2 ,构造矩阵[[p, 1], [-q, 0]],初始矩阵为[S1, S0]。
1 //2017-08-05 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #define ll unsigned long long 7 8 using namespace std; 9 10 ll p, q; 11 const int N = 10; 12 13 struct Matrix{ 14 ll a[N][N]; 15 int r, c; 16 }ori, res; 17 18 void init(){ 19 memset(res.a, 0, sizeof(res.a)); 20 res.r = 1; res.c = 2; 21 res.a[1][1] = p; 22 res.a[1][2] = 2; 23 ori.r = 2; ori.c = 2;//构造矩阵 24 ori.a[1][1] = p; 25 ori.a[1][2] = 1; 26 ori.a[2][1] = -q; 27 ori.a[2][2] = 0; 28 } 29 30 Matrix multi(Matrix x, Matrix y)//矩阵乘法 31 { 32 Matrix z; 33 memset(z.a, 0, sizeof(z.a)); 34 z.r = x.r, z.c = y.c; 35 for(int i = 1; i <= x.r; i++){ 36 for(int k = 1; k <= x.c; k++)//加速优化 37 { 38 if(x.a[i][k] == 0) continue; 39 for(int j = 1; j<= y.c; j++) 40 z.a[i][j] = (z.a[i][j] + (x.a[i][k] * y.a[k][j])); 41 } 42 } 43 return z; 44 } 45 46 void Matrix_pow(int n)//矩阵快速幂 47 { 48 while(n){ 49 if(n & 1) 50 res = multi(res, ori); 51 ori = multi(ori, ori); 52 n >>= 1; 53 } 54 printf("%llu\n", res.a[1][1]); 55 } 56 57 58 int main(){ 59 int T, n; 60 scanf("%d", &T); 61 int kase = 0; 62 while(T--){ 63 scanf("%lld%lld%d", &p, &q, &n); 64 init(); 65 printf("Case %d: ", ++kase); 66 if(n == 0)printf("2\n"); 67 else if(n == 1)printf("%llu\n", p); 68 else Matrix_pow(n-1); 69 } 70 71 return 0; 72 }