Algebraic Problem LightOJ - 1070 (递推+矩阵快速幂)

Given the value of a+b and ab you will have to find the value of a^n+b^n. 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 0^0.

Output
For each test case, print the case number and (a^n+b^n) modulo 2^64.

Sample Input
2
10 16 2
7 12 3
Sample Output
Case 1: 68
Case 2: 91

思路:假设f(n)=a^n+b^n,那么可推得f(n)=f(n-1)*(a+b)-f(n-2)*a*b,然后用矩阵快速幂来搞即可。

注意:模2^64,定义成unsigned long long 类型,因为无符号类型超过最大范围的数与该数%最大范围 的效果是一样的

代码如下

#include <iostream> 
#include <cstring>
#include <cstdio>
using namespace std; 
#define LL long long 
#define ULL unsigned long long 
//const int mod=7; 
struct matrix
{
    ULL x[2][2];
};
matrix mutimatrix(matrix a,matrix b)
{
    matrix temp; 
    memset(temp.x,0,sizeof(temp.x));    
    for(int i=0;i<2;i++)
    for(int j=0;j<2;j++)
    for(int k=0;k<2;k++)
    {
        temp.x[i][j]+=a.x[i][k]*b.x[k][j];
        //temp.x[i][j]%=mod;
    }
    return temp;
}

matrix k_powmatrix(matrix a,LL n)
{
    matrix temp;
    memset(temp.x,0,sizeof(temp.x));
    for(int i=0;i<2;i++)
    temp.x[i][i]=1;

    while(n)
    {
        if(n&1)
        temp=mutimatrix(temp,a);

        a=mutimatrix(a,a);
        n>>=1;
    }
    return temp;
} 


int main()
{
        int T;
        scanf("%d",&T);
        for(int cas=1;cas<=T;cas++)
        {
            ULL q,p,n;
            scanf("%llu %llu %llu",&p,&q,&n); 
            if(n==0)
            {
                printf("Case %d: %llu\n",cas,2);
                continue;
            }
            if(n==1)
            {
                printf("Case %d: %llu\n",cas,p);
                continue;
            }
            matrix st;
            memset(st.x,0,sizeof(st.x));
            st.x[0][0]=p;
            st.x[0][1]=1;
            st.x[1][0]=-q;
            st.x[1][1]=0;
            matrix init;
            memset(init.x,0,sizeof(init.x));

            init.x[0][0]=p;
            init.x[0][1]=2;
            st=k_powmatrix(st,n-1);
            st=mutimatrix(init,st);

            printf("Case %d: %llu\n",cas,st.x[0][0]);
        }
        return 0; 
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值