UVA-10655 Contemplation! Algebra (矩阵)
题目大意:给出a+b的值和ab的值,求a^n+b^n的值。
题目分析:有种错误的方法是这样的:利用已知的两个方程联立,求解出a和b,进而求出答案。这种方法之所以错,是因为这种方法有局限性。联立之后会得到一个二元一次方程,只有当该方程有实数解确切的说是当某个数据满足该方程有实数解时,这种方法得到的结果才有可能正确。显然,题中数据不可能这么片面。正确的方法是这样的:
令a+b=A,ab=B,S(n)=an+bn。则S(n)=an+bn=(a+b)(an-1+bn-1)-abn-1-an-1b=(a+b)(an-1+bn-1)-ab(an-2+bn-2)=A*S(n-1)-B*S(n-2) (n≥2)。
由此构造2x2的矩阵:matrix[1][1]=A,matrix[1][2]=-B;
matrix[2][1]=1,matrix[2][2]=0;
n=1或n=0时,答案显然。
要注意:数据中可能会出现A=B=0的情况,此时a=b=0,所以不能简单的判定当A=B=0时就结束输入数据。
代码如下:
1 # include<iostream> 2 # include<cstdio> 3 # include<cmath> 4 # include<cstring> 5 # include<algorithm> 6 using namespace std; 7 # define LL long long 8 struct matrix 9 { 10 int r,c; 11 LL m[3][3]; 12 matrix(int _r,int _c):r(_r),c(_c){} 13 }; 14 void init(matrix &m,int a,int b) 15 { 16 m.m[1][1]=a,m.m[1][2]=-b; 17 m.m[2][1]=1,m.m[2][2]=0; 18 } 19 matrix multiply(matrix a,matrix b) 20 { 21 matrix m(a.r,b.c); 22 for(int i=1;i<=m.r;++i){ 23 for(int j=1;j<=m.c;++j){ 24 m.m[i][j]=0; 25 for(int k=1;k<=a.c;++k) 26 m.m[i][j]+=a.m[i][k]*b.m[k][j]; 27 } 28 } 29 return m; 30 } 31 matrix matrix_pow(matrix m,int n) 32 { 33 if(n==0){ 34 m.m[1][1]=m.m[2][2]=1; 35 m.m[1][2]=m.m[2][1]=0; 36 return m; 37 } 38 if(n==1) 39 return m; 40 matrix res=matrix_pow(m,n/2); 41 res=multiply(res,res); 42 if(n&1) 43 res=multiply(res,m); 44 return res; 45 } 46 int main() 47 { 48 LL a,b,n; 49 while(scanf("%lld%lld%lld",&a,&b,&n)==3) 50 { 51 if(n==0){ 52 printf("2\n"); 53 continue; 54 } 55 if(n==1){ 56 printf("%d\n",a); 57 continue; 58 } 59 matrix mat(2,2); 60 init(mat,a,b); 61 mat=matrix_pow(mat,n-2); 62 matrix ans(2,1); 63 ans.m[1][1]=a*a-2*b; 64 ans.m[2][1]=a; 65 ans=multiply(mat,ans); 66 printf("%lld\n",ans.m[1][1]); 67 } 68 return 0; 69 }