1. 程式人生 > >LightOJ 1070 Algebraic Problem (推導+矩陣高速冪)

LightOJ 1070 Algebraic Problem (推導+矩陣高速冪)

思路 註意 結果 string blog font log 得到 code

題目鏈接:

problem=1070">LightOJ 1070 Algebraic Problem

題意:已知a+b和ab的值求a^n+b^n。結果模2^64。

思路:

1.找遞推式

技術分享

得到遞推式之後就是矩陣高速冪了

註意:模2^64,定義成unsigned long long 類型,由於無符號類型超過最大範圍的數與該數%最大範圍 的效果是一樣的。



AC代碼:

#include<stdio.h>
#include<string.h>
#define LL unsigned long long

struct Matrix {
	LL m[10][10];
};
LL n;
Matrix geti(LL n) {
	LL i;
	Matrix b;
	memset(b.m,0,sizeof b.m);
	for(i=0;i<2;i++)
		b.m[i][i]=1;
	return b;
}

Matrix matrixmul(Matrix a,Matrix b) {
	LL i,j,k;
	Matrix c;
	for(i=0;i<2;i++) {
		for(j=0;j<2;j++) {
			c.m[i][j]=0.0;
			for(k=0;k<2;k++) {
				c.m[i][j]+=(a.m[i][k]*b.m[k][j]);
			}
		}
	}
	return c;
}


Matrix quickpow(Matrix a,LL p) {
	Matrix m=a;
	Matrix b=geti(n);
	while(p) {
		if(p%2)
			b=matrixmul(b,m);
		p/=2;
		m=matrixmul(m,m);
	}
	return b;
}


int main() {
	LL t;
	LL p,q;
	int cas=1;
	Matrix pp,init,ans;
	//printf("%llu\n",kmod);
	scanf("%llu",&t);
	while(t--) {
		scanf("%llu %llu %llu",&p,&q,&n);
		memset(pp.m,0,sizeof pp);
		pp.m[0][0]=p;
		pp.m[0][1]=1;
		pp.m[1][0]=-q;
		pp.m[1][1]=0;

		init.m[0][0]=p;
		init.m[0][1]=2;
		init.m[1][0]=0;
		init.m[1][1]=0;

		printf("Case %d: ",cas++);
		if(n==0){
			printf("%llu\n",init.m[0][1]);
		}
		else if(n==1){
			printf("%llu\n",init.m[0][0]);
		}
		else {
			ans=quickpow(pp,n-1);
			ans=matrixmul(init,ans);
			printf("%llu\n",ans.m[0][0]);
		}
	}
	return 0;
}
/*

 */


LightOJ 1070 Algebraic Problem (推導+矩陣高速冪)