九度oj1081递推数列的算法

来源:互联网 发布:上海网络视听产业基地 编辑:程序博客网 时间:2024/05/16 09:27

这个题用到了矩阵二分乘法,之前没接触过这个东西,这个矩阵二分乘法确实不错,从网上学了一篇文章,进入百度搜九度1081就能搜索到的那边文章,从那里,我学到了矩阵二分乘法和递归算法。

可以将原本o(n)的复杂度弄成o(logn),对于这个题!别小看这个n和logn,比如n为1024,logn居然只有10,差太远了,天壤之别,你logn只要算10次,人家要1024次。

关于递归方法和非递归方法,非递归方法很简便但是设计的时候难一些,既然有好的方法,当然要有 追求 好 的 追求。

附上递归(递归的算法和百度里找的那个一致,没什么看头,非常感谢那位仁兄的代码!具体网址我就不写了)和非递归的AC代码。PS:很容易发现这个题的2*2矩阵M的p,q都为1的时候便是Fibonacci数列了,也就是说这个题其实比Fibonacci数列更一般化,学了这么久编程,终于会用非递归的某!种方法解决一下Fibonacci数列的指数型调用次数问题了,当时看deitel的书的时候还想着如何非递归解决,一直没解决。。傻如猪的感觉有没有?。

#include<iostream>  using std::cin;  using std::cout;  using std::endl;  #include<cassert>        //完成任意2个2*2矩阵相乘  void func(int t[2][2],int s[2][2])  {      int tt[2][2];         tt[0][0] = t[0][0]*s[0][0] + t[0][1]*s[1][0];          tt[0][1] = t[0][0]*s[0][1] + t[0][1]*s[1][1];          tt[1][0] = t[1][0]*s[0][0] + t[1][1]*s[1][0];          tt[1][1] = t[1][0]*s[0][1] + t[1][1]*s[1][1];      for(int i=0;i<=1;i++)         for(int j=0;j<=1;j++)             t[i][j]=tt[i][j]%10000; }      //完成sf的kfc次幂 递归函数  void calCur(int sf[2][2], int kfc)  {      int sd[2][2]={{sf[0][0],sf[0][1]},{sf[1][0],sf[1][1]}};           if(kfc == 1)          return;          if(kfc % 2 == 1)      {          calCur(sf,kfc-1);         func(sf,sd);     }      else    {          calCur(sf,kfc/2);         func(sf,sf);     }  }      int main()  {      int a[2][2];     int a0, a1, p, q, k;      int c;                  while(cin >> a0 >> a1 >> p >> q >> k)      {          assert(k >= 0);          a[0][0] = p,a[0][1] = q;          a[1][0] = 1,a[1][1] = 0;                      if(k == 0)          {              cout << a0 % 10000 << endl;              continue;          }          if(k == 1)          {              cout << a1 % 10000 << endl;              continue;          }                     calCur(a,k-1);         c = a[0][0]*a1 + a[0][1]*a0;                      cout << c % 10000 << endl;      }              return 0;  }    /**************************************************************     Problem: 1081     User: true14fans     Language: C++     Result: Accepted     Time:20 ms     Memory:1520 kb ****************************************************************/


 

#include<iostream>using std::cin;using std::cout;using std::endl;#define M 10000int main(){int a0,a1,p,q,k,kk;int t1,t2,t3,t4;int M00,M01,M10,M11;int temprow1,row1,row2;while(cin>>a0>>a1>>p>>q>>k){if(k==0){cout << a0 << endl;continue;}if(k==1){cout << a1 << endl;continue;}M00=p%M,M01=q%M,M10=1,M11=0;row1=a1,row2=a0;kk=k-1;while(kk>=1){if(kk%2==0){//临时矩阵存当前分割时的矩阵,分割矩阵次数递增t1=(M00*M00+M01*M10)%M;t2=(M00*M01+M01*M11)%M;t3=(M10*M00+M11*M10)%M;t4=(M10*M01+M11*M11)%M;M00=t1;M01=t2;M10=t3;M11=t4;kk/=2;}else{temprow1=row1;//没有temprow1就eggs broken吧,我在VC6.0里输入20 1 1 14 (0-5) 括号里面为4时就通不过row1=(M00*row1+M01*row2)%M;row2=(M10*temprow1+M11*row2)%M;--kk;}}cout << row1 << endl;}return 0;}


 

 

 

原创粉丝点击