题目链接:https://vjudge.net/problem/UVA-10655
题意:
a+b、ab的值分别为p、q,求a^n+b^n。
题解:
1.a、b未知,且直接求出a、b也不太实际。
2.看到 a^n+b^n 这个式子就想到二阶齐次递推式的通项公式,然后就想是否能通过通项公式反推回递推式。结果发现a、b的值是不能确定是否相等的,而求二阶齐次递推式的通项公式时,是需要根据根的情况来分类求解的,所以此题不适应。
3.那么,就直接对 a^n+b^n 做一下变形:
4.得到递推式之后,就直接构造矩阵,然后快速幂。
代码如下:


1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 1e6+100; 18 19 const int Size = 2; 20 struct MA 21 { 22 LL mat[Size][Size]; 23 void init() 24 { 25 for(int i = 0; i<Size; i++) 26 for(int j = 0; j<Size; j++) 27 mat[i][j] = (i==j); 28 } 29 }; 30 31 MA mul(MA x, MA y) 32 { 33 MA ret; 34 memset(ret.mat, 0, sizeof(ret.mat)); 35 for(int i = 0; i<Size; i++) 36 for(int j = 0; j<Size; j++) 37 for(int k = 0; k<Size; k++) 38 ret.mat[i][j] += 1LL*x.mat[i][k]*y.mat[k][j]; 39 return ret; 40 } 41 42 MA qpow(MA x, LL y) 43 { 44 MA s; 45 s.init(); 46 while(y) 47 { 48 if(y&1) s = mul(s, x); 49 x = mul(x, x); 50 y >>= 1; 51 } 52 return s; 53 } 54 55 56 int main() 57 { 58 LL p, q, n, f[2]; 59 while(scanf("%lld%lld%lld", &p,&q,&n)==3) 60 { 61 f[0] = 2; f[1] = p; 62 if(n<=1) 63 { 64 printf("%lld\n", f[n]); 65 continue; 66 } 67 68 MA s; 69 memset(s.mat, 0, sizeof(s.mat)); 70 s.mat[0][0] = p; s.mat[0][1] = -q; 71 s.mat[1][0] = 1; s.mat[1][1] = 0; 72 73 s = qpow(s, n-1); 74 LL ans = 1LL*s.mat[0][0]*f[1] + 1LL*s.mat[0][1]*f[0]; 75 printf("%lld\n", ans); 76 } 77 }