LightOJ-1070- Algebraic Problem (矩陣快速冪)
原題連結:
Given the value of a+b and ab you will have to find the value of an+bn. a and b not 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
題意:
給出a+b的和p,ab的積q,要求計算出a^n+b^n的值。
題解:
利用遞推公式:a^n+b^n=(a+b)(a^(n-1)+b^(n-1))-(ab)(a^(n-2)+b^(n-2))
建立矩陣關係:A=(p,1,-q,0)(2x2方陣)
(ans[n],ans[n-1])=A^(n-2)(ans[2],ans[1])
**注意:**由於A的指數為n-2,所以要對於n=0,1,2的三種情況進行特判。
由於題目要求mod2^64,所以資料型別必須是unsigned long long,至於mod2^64,這個好像沒有必要。
附上AC程式碼:
#include <iostream> #include <cstring> #include <cstdio> using namespace std; #define LL unsigned long long struct mat { LL a[2][2]; mat() { memset(a,0,sizeof(a)); } mat operator * (mat b) { mat tmp; for(int i=0;i<2;++i) for(int j=0;j<2;++j) for(int k=0;k<2;++k) tmp.a[i][j]+=(a[i][k]*b.a[k][j]); return tmp; } }; LL p,q,n; mat quickpow(mat a,LL b) { mat res; for(int i=0;i<2;++i) res.a[i][i]=1; while(b!=0) { if(b&1) res=res*a; a=a*a; b>>=1; } return res; } int main() { int t; scanf("%d",&t); for(int cas=1;cas<=t;cas++) { scanf("%llu%llu%llu",&p,&q,&n); if(n==0) { printf("Case %d: 2\n",cas); continue; } if(n==1) { printf("Case %d: %llu\n",cas,p); continue; } if(n==2) { printf("Case %d: %llu\n",cas,p*p-2*q); continue; } mat A,ans; ans.a[0][1]=p,ans.a[0][0]=(p*p-2*q); A.a[0][0]=p,A.a[0][1]=1,A.a[1][0]=-q; A=quickpow(A,n-2); ans=ans*A; printf("Case %d: %llu\n",cas,ans.a[0][0]); } return 0; }
歡迎評論!