1. 程式人生 > >LightOJ-1070- Algebraic Problem (矩陣快速冪)

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))-(a
b)(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;
}

歡迎評論!