BestCoder Round #80 C (hdu5667) 【矩阵快速幂】

链接:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=688&pid=1003

题意:中文题,给你f1,f2,fn=a^b+fn-1^c+fn-2,让你求fn

分析:看公式一眼矩阵快速幂,但是式子里面有fn-1^c,直接上矩阵是求不出的,我们可以观察到式子的每项都是以a为底的数,f1=a^0,f2=a^b,f3=a^(b+bc),f4=a^(b+(b+bc)*c+b);

设gx为fx的指数表达式,则gn=b+gn-1*c+gn-2,我们现在可以对g进行矩阵快速幂求出第n项的指数,然后快速幂求出最后的答案。

注意,指数取模要根据费马小定理:a^n%p与a^(n%(p-1))%p同余,所以指数的模减一。

还有数据中有a%p==0,如果不特判结果就错了。

代码:

#include <algorithm>
#include <iostream>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <set>
#include <map>
#include <ctime>
#define INF 0x3f3f3f3f
#define Mn 100010
#define Mm 200010
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul (u<<1)
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
struct Matrix {
	ll mt[3][3];
	 Matrix() {
       for(int i=0; i<3; i++)
           for(int j=0; j<3; j++)
               mt[i][j]=0;
    }
};
Matrix Mult(Matrix b,Matrix a,ll p) {
	Matrix c;
	for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++) 
		(c.mt[i][j]+=a.mt[i][k]*b.mt[k][j]%p)%=p;
	return c;
}
Matrix pow(Matrix a,ll n,ll p) {
	Matrix re;
    for(int i=0; i<3; i++) re.mt[i][i]=1;
    while(n) {
        if(n%2) re=Mult(re,a,p);
        a=Mult(a,a,p);
        n>>=1;
    }
    return re;
}
ll pow(ll a,ll n,ll p) {
	int b=1;
	while(n) {
		if(n%2) b=a*b%p;
	   	a=a*a%p;
		n>>=1;	
	}
	return b;
}
int main() {
   	int t;
	scanf("%d",&t);
	while(t--) {
		int a,b,c;
		ll n,p;
		Matrix init,tr;
		scanf("%I64d%d%d%d%I64d",&n,&a,&b,&c,&p);
		init.mt[0][0]=b;
		init.mt[2][0]=b;
		tr.mt[0][0]=1;
		tr.mt[1][2]=1;
		tr.mt[2][0]=1;
		tr.mt[2][1]=1;
		tr.mt[2][2]=c;
		if(n==1) {
			printf("1\n");
		} else if(n==2) {
			printf("%I64d\n",pow((ll)a,b,p));
		} else {
			if(a%p==0) printf("0\n");
			else {
				init=Mult(init,pow(tr,n-2,p-1),p-1);
				printf("%I64d\n",pow((ll)a,init.mt[2][0],p));	
			}
		}
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值