HDU5667——费马小定理
Posted mingusu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU5667——费马小定理相关的知识,希望对你有一定的参考价值。
题目链接
------------恢复内容开始------------
题目链接:https://vjudge.net/problem/HDU-5667
题目意思:按照递推式求出第n项对p求余的结果(p为质数)。
Sequence
Now there are many foods,but he does not want to eat all of them at once,so he find a sequence.
fn=?????1,ab,abfcn−1fn−2,n=1n=2otherwisefn={1,n=1ab,n=2abfn−1cfn−2,otherwise
He gives you 5 numbers n,a,b,c,p,and he will eat fnfn foods.But there are only p foods,so you should tell him fnfn mod p.
Input The first line has a number,T,means testcase.
Each testcase has 5 numbers,including n,a,b,c,p in a line.
1≤T≤10,1≤n≤1018,1≤a,b,c≤109 1≤T≤10,1≤n≤1018,1≤a,b,c≤109,pp is a prime number,and p≤109+7p≤109+7.Output Output one number for each case,which is fnfn mod p.Sample Input
1 5 3 3 3 233
Sample Output
190
题目思路:先对两边取对数,f(n)=a^b*f(n-1)^c*f(n-2),f(2)=a^b,f(1)=1,可以看出每一项都是一个以a为底的数,我们对递推公式两边取log a,变成g(n)=b+c*g(n-1)+g(n-2),然后就可以构造矩阵了;
[ g(n-1),g(n-2),1]*A=[g(n),g(n-1),1],求矩阵A就可以了;
A=c,1,0
1,0,0
b,0,1
g(n)表示的是指数,[g(n),g(n-1),1] = [g(2),g(1),1]*A^(n-2),我们只需要g(n),在求A^(n-2)时用到快速幂,由于g(n)是指数,而且mod是素数( a^g(n) )%mod =a^(g(n)%(mod-1))%mod,费马小定理!!!!然后单独考虑n=1,2的情况,f(1)=1,f(2)=a^b,直接快速幂;
1 #include <set> 2 #include <map> 3 #include <stack> 4 #include <queue> 5 #include <math.h> 6 #include <vector> 7 #include <string> 8 #include <utility> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <iostream> 13 #include <algorithm> 14 #include <functional> 15 16 using namespace std; 17 struct Matrax{ 18 long long m[10][10]; 19 }ter; 20 long long mod; 21 Matrax muli(Matrax a,Matrax b){ 22 Matrax p; 23 for(int i=0;i<3;i++) 24 for(int j=0;j<3;j++){ 25 p.m[i][j]=0; 26 for(int k=0;k<3;k++){ 27 p.m[i][j]+=(a.m[i][k]*b.m[k][j])%(mod-1); 28 p.m[i][j]%=mod-1; 29 } 30 } 31 return p; 32 }//矩阵乘法 33 Matrax quick_mod(Matrax a,long long b){ 34 Matrax ans=ter; 35 while(b){ 36 if(b&1){ 37 ans=muli(ans,a); 38 b--; 39 } 40 else { 41 b>>=1; 42 a=muli(a,a); 43 } 44 } 45 return ans; 46 }//快速幂 47 long long qmod(long long a,long long b){ 48 long long ans=1; 49 while(b){ 50 if(b&1){ 51 ans=ans*a%mod; 52 b--; 53 } 54 b>>=1; 55 a=a*a%mod; 56 } 57 return ans; 58 } 59 int main(){ 60 int t; 61 scanf("%d",&t); 62 while(t--){ 63 long long n,a,b,c; 64 scanf("%I64d%I64d%I64d%I64d%I64d",&n,&a,&b,&c,&mod); 65 if(n==1){ 66 puts("1"); 67 continue; 68 } 69 if(n==2){ 70 printf("%I64d ",qmod(a,b)); 71 continue; 72 } 73 ter.m[0][0]=1; 74 ter.m[0][1]=0; 75 ter.m[0][2]=0; 76 ter.m[1][0]=0; 77 ter.m[1][1]=1; 78 ter.m[1][2]=0; 79 ter.m[2][0]=0; 80 ter.m[2][1]=0; 81 ter.m[2][2]=1;//初始化E矩阵 因为本题推出来是三元相加,所以用三维矩阵 82 n-=2; 83 Matrax A,B; 84 A.m[0][0]=0; 85 A.m[0][1]=1; 86 A.m[0][2]=0; 87 A.m[1][0]=1; 88 A.m[1][1]=c; 89 A.m[1][2]=0; 90 A.m[2][0]=0; 91 A.m[2][1]=b; 92 A.m[2][2]=1;//这里是中间连乘部分的矩阵 93 A=quick_mod(A,n); 94 B.m[0][0]=0; 95 B.m[0][1]=b; 96 B.m[0][2]=1; 97 B.m[1][0]=0; 98 B.m[1][1]=0; 99 B.m[1][2]=0; 100 B.m[2][0]=0; 101 B.m[2][1]=0; 102 B.m[2][2]=0; 103 B=muli(B,A);//这里是最初始的矩阵 104 // cout<<B.m[0][1]<<endl; 105 // cout<<a<<endl; 106 printf("%I64d ",qmod(a,B.m[0][1]+mod-1)); 107 } 108 return 0; 109 }
以上是关于HDU5667——费马小定理的主要内容,如果未能解决你的问题,请参考以下文章