hdu 4549 M斐波那契数列(快速幂 矩阵快速幂 费马小定理)

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4549;

题目是中文的很容易理解吧。可一开始我把题目看错了,这毛病哈哈。 一开始我看错题时,就用了一个快速幂来解,不用说肯定wa,看题目的通过率也不高,我想会不会有啥坑啊。然而我就是那大坑,哈哈。

不说了,直接说题吧,先讨论k=1,2,3;时的解。这应该会解吧,不多说了;

从第四项开始f(4)=a^1+b^2;f(5)=a^2+b^3;f(6)=a^3+b^5......; 看出来了吧,a上的指数成斐波那契数列,b的也成,而且a的指数是b的前一项;

那么就打表求斐波那契数列呗,不敢,范围太大,又爆内存又超时的。

f(n)=a^k(n-4)+b^k(n-3);其中n>=4;k(0)=1;k(1)=2;

用矩阵来求斐波那契数列的相邻两项有[k[n-2],k[n-1]]*[0 1]

[1 1]

上式等于[k[n-1],k[n]];

那么要求[k[n-4],k[n-3]]=[1,2]*[0 1]^(n-3)

[1 1]

这样就可以用矩阵快速幂来求k[n-4],k[n-3]了;

但光这样还不够,在矩阵快速幂过程中还得取模,不然会溢出。

由费马小定理在p为素数的情况下对任意的整数x都有x^p==x(mod p)

;如果x不能被p整除有x^(p-1)=1(mod p);由于a,b<1e9;所以不能被1e9+7整除, 求出了k[n],则a^k[n]%p=a^(k[n]%(p-1))%p;

证明如下: k[n]=m*(p-1)+d;那么a^k[n]%p=a^[(m*(p-1))+d]%p=(a^[m*(p-1)]%p*a^(d)%p)%p;

由费马小定理可知a^(m*(p-1))%p=1; 而d=k[n]%(p-1);得证;

所以矩阵快速幂时要对1e+6取模就行了; 当k(n)求出来是再进行快速幂运算就可以了,复杂度为2*log2(n); 注意要开longlong不然会溢出。

下面看代码:

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<math.h>
  7 const long long N=1e9+7;
  8 const long long M=1e9+6;
  9 typedef long long ll;
 10 void kk(ll y);
 11 ll pp(ll x,ll y);
 12 ll b[2][2];
 13 ll a[2][2];
 14 using namespace std;
 15 int main(void)
 16 {
 17     ll i,j,k,p,q,n,m;
 18
 19     while(scanf("%lld%lld%lld",&p,&q,&k)!=EOF)
 20     {
 21         if(k==0)
 22         {
 23             printf("%lld\n",p%N);
 24
 25         }
 26         else if(k==1)
 27         {
 28             printf("%lld\n",q%N);
 29
 30         }
 31         else if(k==2)
 32         {
 33             printf("%lld\n",(p%N*q%N)%N);
 34         }
 35         else
 36         {
 37             k=k-3;
 38             kk(k);
 39             ll p1=(b[0][0]%M+2*b[1][0]%M)%M;//求的k(n-4)
 40             ll p2=(b[0][1]%M+2*b[1][1]%M)%M;//k[n-3]
 41             ll x1=pp(p,p1);//a^k(n-4);
 42             ll x2=pp(q,p2);//b^k(n-3);
 43             ll dd=(x1*x2)%N;//d=(a^k(n-4)*b^k(n-3))%N;
 44             printf("%lld\n",dd);
 45
 46         }
 47
 48     }
 49
 50     return 0;
 51
 52 }
 53
 54 ll pp(ll x,ll y)//快速幂
 55 {
 56     ll p=x;
 57     ll q=1;
 58
 59     while(y)
 60     {
 61         if(y&1)
 62         {
 63             q=(q%N*p%N)%N;
 64         }
 65         p=(p%N*p%N)%N;
 66
 67         y=y/2;
 68     }
 69     return q;
 70
 71 }
 72
 73
 74 void kk(ll y)//矩阵快速幂  形式和快速幂基本一样。
 75 {
 76     ll i,j,k;
 77     ll x1,x2,x3,x4;
 78     a[0][0]=0;//a为变换矩阵;
 79     a[0][1]=1;
 80     a[1][0]=1;
 81     a[1][1]=1;
 82     b[0][0]=1;//b为单位阵;
 83     b[0][1]=0;
 84     b[1][0]=0;
 85     b[1][1]=1;
 86
 87     while(y)
 88     {
 89         if(y&1)
 90         {
 91             x1=((b[0][0]*a[0][0])%M+(b[0][1]*a[1][0])%M)%M;
 92             x2=((b[0][0]*a[0][1])%M+(b[0][1]*a[1][1])%M)%M;
 93             x3=((b[1][0]*a[0][0])%M+(b[1][1]*a[1][0])%M)%M;
 94             x4=((b[1][0]*a[0][1])%M+(b[1][1]*a[1][1])%M)%M;
 95             b[0][0]= x1;
 96             b[0][1]=x2;
 97             b[1][0]=x3;
 98             b[1][1]=x4;
 99         }
100         x1=((a[0][0]*a[0][0])%M+(a[0][1]*a[1][0])%M)%M;
101         x2=((a[0][0]*a[0][1])%M+(a[0][1]*a[1][1])%M)%M;
102         x3=((a[1][0]*a[0][0])%M+(a[1][1]*a[1][0])%M)%M;
103         x4=((a[1][0]*a[0][1])%M+(a[1][1]*a[1][1])%M)%M;
104         a[0][0]=x1;
105         a[0][1]=x2;
106         a[1][0]=x3;
107         a[1][1]=x4;
108         y/=2;
109
110     }
111
112
113
114
115 }
时间: 2024-10-06 00:28:52

hdu 4549 M斐波那契数列(快速幂 矩阵快速幂 费马小定理)的相关文章

hdu 4549 M斐波那契数列(矩阵快速幂,快速幂降幂)

http://acm.hdu.edu.cn/showproblem.php?pid=4549 f[0] = a^1*b^0%p,f[1] = a^0*b^1%p,f[2] = a^1*b^1%p.....f[n] = a^fib[n-1] * b^fib[n-2]%p. 这里p是质数,且a,p互素,那么我们求a^b%p,当b很大时要对b降幂. 因为a,p互素,那么由费马小定理知a^(p-1)%p = 1.令b = k*(p-1) + b',a^b%p = a^(k*(p-1)+b')%p = a

HDU 4549 M斐波那契数列 ( 矩阵快速幂 + 费马小定理 )

HDU 4549 M斐波那契数列 (  矩阵快速幂 + 费马小定理  ) 题意:中文题,不解释 分析:最好的分析就是先推一推前几项,看看有什么规律 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef __int64 LL; #define CLR( a, b ) memset( a, b, sizeof(a) ) #define MOD 100000

【矩阵快速幂】HDU 4549 : M斐波那契数列(矩阵嵌套)

[题目链接]click here~~ [题目大意] M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗?对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行. [Source] :2013金山西山居创意游戏程序挑战赛――初赛(2) [解题思路] 这个题稍微有点难度,就

HDU 4549 M斐波那契数列(矩阵快速幂)

Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗? Input 输入包含多组测试数据: 每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 ) Output 对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模

HDU 4549 M斐波那契数列(矩阵快速幂&amp;费马小定理)

ps:今天和战友聊到矩阵快速幂,想到前几天学长推荐去刷矩阵专题,挑了其中唯一一道中文题,没想到越过山却被河挡住去路... 题目链接:[kuangbin带你飞]专题十九 矩阵 R - M斐波那契数列 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u 题意 Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2]

hdu 4549 M斐波那契数列 矩阵快速幂+欧拉定理

M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = aF[1] = bF[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗? Input 输入包含多组测试数据:每组数据占一行,包含3个整数a, b,

矩阵快速幂 [HDU 4549] M斐波那契数列

M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1609    Accepted Submission(s): 460 Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = aF[1] = bF[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a,

HDU 4549 M斐波那契数列(矩阵快速幂 费马小定理)

M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗? Input 输入包含多组测试数据: 每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 ) Output 对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行. Samp

hdu 4549 M斐波那契数列(矩阵高速幂,高速幂降幂)

http://acm.hdu.edu.cn/showproblem.php?pid=4549 f[0] = a^1*b^0%p,f[1] = a^0*b^1%p,f[2] = a^1*b^1%p.....f[n] = a^fib[n-1] * b^fib[n-2]%p. 这里p是质数,且a,p互素,那么我们求a^b%p,当b非常大时要对b降幂. 由于a,p互素,那么由费马小定理知a^(p-1)%p = 1.令b = k*(p-1) + b'.a^b%p = a^(k*(p-1)+b')%p =