LightOJ 1070 - Algebraic Problem 矩阵快速幂

题链:http://lightoj.com/volume_showproblem.php?problem=1070

1070 - Algebraic Problem
Time Limit: 2 second(s)Memory Limit: 32 MB

Given the value of a+b and ab you will have to find the value of an+bna 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

Output for Sample Input

2

10 16 2

7 12 3

Case 1: 68

Case 2: 91

 

题意:

给你p=a+b, q=ab

算出 (a^n+b^)mod2^64

做法:

mod 2^64所以开 unsigned long long ,llu 就行了,达到上限会自动取模的。

然后就是公式了。我是在推公式中找到的规律。

a^2+b^2=(a+b)*(a+b)-2*a*b

a^3+b^3=(a^2+b^2)*(a+b)-a*b(a+b)

a^4+b^4=(a^3+b^3)*(a+b)-a*b(a^2+b^2)

设G(n)=a^n+b^n

G(n)=G(n-1)*p-G(G-2)*q

然后就是快速幂了。.

#include<stdio.h>
#include<string.h>
#define Matr 5 //矩阵大小,注意能小就小   矩阵从1开始   所以Matr 要+1   最大可以100
#define ll unsigned long long
struct mat//矩阵结构体,a表示内容,size大小 矩阵从1开始   但size不用加一
{
    ll a[Matr][Matr];
    mat()//构造函数
    {
        memset(a,0,sizeof(a));
    }
};
int Size=  2; 

mat multi(mat m1,mat m2)//两个相等矩阵的乘法,对于稀疏矩阵,有0处不用运算的优化 
{
    mat ans=mat(); 
    for(int i=1;i<=Size;i++)
        for(int j=1;j<=Size;j++)
            if(m1.a[i][j])//稀疏矩阵优化 
                for(int k=1;k<=Size;k++)
                    ans.a[i][k]=(ans.a[i][k]+m1.a[i][j]*m2.a[j][k]); //i行k列第j项
    return ans;
}

mat quickmulti(mat m,ll n)//二分快速幂 
{
    mat ans=mat();
    int i;
    for(i=1;i<=Size;i++)ans.a[i][i]=1;
    while(n)
    {
        if(n&1)ans=multi(m,ans);//奇乘偶子乘 挺好记的.
        m=multi(m,m);
        n>>=1;
    }
    return ans;
}

void print(mat m)//输出矩阵信息,debug用   
{  
    int i,j;  
    printf("%d\n",Size);  
    for(i=1;i<=Size;i++)  
    {  
        for(j=1;j<=Size;j++)
			printf("%llu ",m.a[i][j]);  
        printf("\n");  
    }  
}  
int main()
{  
	/*
	ll a,b;
	while(scanf("%llu",&a)!=EOF)
		printf("%llu\n",-a+18446744073709551615+1);
	*/
	int t;
	int cas=1;
	scanf("%d",&t);
	while(t--)
	{
		ll p,q,n;
		int p1,q1;
		scanf("%lld%lld%llu",&p,&q,&n);// p a+b q ab 



		ll tem=18446744073709551615-q+1;

		mat gouzao=mat(),chu=mat();//构造矩阵  初始矩阵   
		chu.a[1][1]=p;
		chu.a[1][2]=p*p+2*tem;
		chu.a[1][3]=q;
		printf("Case %d: ",cas++);
		if(n==0)
			printf("2\n");
		else if(n==1)
			printf("%llu\n",p);
		else if(n==2)
			printf("%llu\n",p*p+2*tem);
		else
		{ 
			gouzao.a[1][1]=0;
			gouzao.a[2][1]=1;
			gouzao.a[1][2]=tem;
			gouzao.a[2][2]=p;  
			//print(gouzao);
			printf("%llu\n",multi(chu,quickmulti(gouzao,n-2)).a[1][2]); 
		} 
	} 
	return 0;
}

/*
ans^=n -
mat ans=mat();
ans.size=Size;
初始化ans矩阵
ans=quickmulti(ans,n,mod);

void print(mat m)//输出矩阵信息,debug用 
{
    int i,j;
    printf(%dn,m.size);
    for(i=1;i=m.size;i++)
    {
        for(j=1;j=m.size;j++)printf(%d ,m.a[i][j]);
        printf(n);
    }
}
*/









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值