zoukankan      html  css  js  c++  java
  • 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
    ",p%N);
     24 
     25         }
     26         else if(k==1)
     27         {
     28             printf("%lld
    ",q%N);
     29 
     30         }
     31         else if(k==2)
     32         {
     33             printf("%lld
    ",(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
    ",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 }
    油!油!you@
  • 相关阅读:
    em
    How to locate a path?
    云图说 | 揭秘云硬盘高可靠性的秘密,速来围观
    【华为云技术分享】开发团队中的任务没人领取,你头疼吗?
    介绍一种更方便的代理池实现方案
    4行Python代码生成图像验证码
    【华为云技术分享】机器学习(02)——学习资料链接
    【华为云技术分享】华为开发者大会HDC.Cloud带你探索强化学习三大挑战及落地实践
    【华为云技术分享】【一统江湖的大前端(8)】matter.js 经典物理
    华为开发者大会HDC.Cloud硬核技术解读:知识图谱构建流程及方法
  • 原文地址:https://www.cnblogs.com/zzuli2sjy/p/4928581.html
Copyright © 2011-2022 走看看