HDU3317---Fibonacci Numbers(矩阵快速幂+pow+log)
来源:互联网 发布:淘宝店铺装修合同 编辑:程序博客网 时间:2024/06/03 09:03
【题目来源】:https://cn.vjudge.net/problem/HDU-3117
【题意】
求第n个斐波那契数,如果这个数值长度大于8位,就输出前四位和后四位。
【思路】
小伙伴说到这道题的时候,我就想到了另外一道题,求k^n的前三位,后三位。
里面使用到了log10函数,log10的使用方法刚才那道题的题解有,自行点击,不再多说。
然后,就是在这道题里求前四位该如何使用:
也就是我们可以把矩阵里的数值使用log10后的数字表示,那me就不会炸,但是0该如何表示呢?用负数把,因为0在log10之后的代表的是1,(log10(0)==1),所以初始矩阵为:
0 0
0 -1
其次就是矩阵乘法该如何写?
在普通矩阵乘法里,0乘任何数都是0,而在log10后的矩阵里,负数代表的是0,所以我们就可以特判,如果”将要相乘”的两个数有一个是-1,那么直接略去,那么普通矩阵里乘法相当于log10后的矩阵里的加法(可以自行模拟想一下),但是会有人问,不仅有乘法,还有加法呢,该怎么算呢?假如将要相加的两个数是x,y,那么他们各自代表的数为:10^x,10^y,那么他们相加就可以变为10^min(x,y)*(1+10^(max(x,y)-min(x,y)),写的有点麻烦,其实就是提取公因式啦。。后面那一大部分用pow函数就可以了。
然后后四位直接矩阵快速幂取模,从样例发现,第40个斐波那契数值刚好大于8位,那么前面的只需要打个表就行。
【代码】
#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n;struct mat{ int a[3][3];//后四位的矩阵 double b[3][3];//前四位的矩阵};mat operator*(mat &s,mat &t)//后四位的矩阵快速幂{ mat r; memset(r.a,0,sizeof(r.a)); for(int i=1; i<=2; i++) for(int j=1; j<=2; j++) for(int k=1; k<=2; k++) { r.a[i][j]+=s.a[i][k]*t.a[k][j]; if(r.a[i][j]>=10000) r.a[i][j]%=10000; } return r;}mat operator/(mat &s,mat &t)//因为“*”被后四位的快速幂占用了,所以换成了'/'(其实什么都可以){ mat r; for(int i=1; i<=2; i++) for(int j=1; j<=2; j++) { int f1=1,f2=1; if(s.b[i][1]<0||t.b[1][j]<0) f1=0;//判断是否存在-1 if(s.b[i][2]<0||t.b[2][j]<0) f2=0; if(!f1&&f2) r.b[i][j]=s.b[i][2]+t.b[2][j]; else if(f1&&!f2) r.b[i][j]=s.b[i][1]+t.b[1][j]; else if(f1&&f2)//若都不是-1 { double x=s.b[i][1]+t.b[1][j],y=s.b[i][2]+t.b[2][j]; r.b[i][j]=min(x,y)+log10(1+pow(10,max(x,y)-min(x,y)));//提取公因式 } else if(!f1&&!f2)//若都是-1,那么负值为-1,相当于普通矩阵的0 r.b[i][j]=-1.0; } return r;}int pow_int(mat base,int k)//后四位{ mat ans; memset(ans.a,0,sizeof(ans.a)); ans.a[1][1]=ans.a[2][2]=1; int cases=0; while(k) { if(k&1) ans=ans*base; base=base*base; k>>=1; } return ans.a[1][1];}double pow_double(mat base,int k)//前四位{ mat ans; ans.b[1][2]=ans.b[2][1]=-1.0; ans.b[1][1]=ans.b[2][2]=log10(1.0); while(k) { if(k&1) ans=ans/base; base=base/base; k>>=1; } int x=(int)ans.b[1][1]; ans.b[1][1]-=x; return pow(10.0,ans.b[1][1])*1000;}int main(){ int p[40];//前39位预处理 p[0]=0; p[1]=1; for(int i=2; i<=39; i++) { p[i]=p[i-1]+p[i-2]; } while(~scanf("%d",&n)) { if(n<=39) printf("%d\n",p[n]); else { mat base; base.a[2][1]=base.a[1][2]=base.a[1][1]=1; base.a[2][2]=0; base.b[1][2]=base.b[2][1]=base.b[1][1]=log10(1.0); base.b[2][2]=-1.0; int r_ans=pow_int(base,n-1); int l_ans=(int)pow_double(base,n-1); printf("%d...%04d\n",l_ans,r_ans); } }}
阅读全文
0 0
- HDU3317---Fibonacci Numbers(矩阵快速幂+pow+log)
- HDU3117-Fibonacci Numbers(矩阵快速幂+log)
- hdu3117 Fibonacci Numbers (矩阵快速幂)
- HDU3117 Fibonacci Numbers(矩阵快速幂)
- 【公式+矩阵快速幂】HDU_3117 Fibonacci Numbers
- Fibonacci(矩阵快速幂)
- HDU 3117 Fibonacci Numbers(矩阵快速幂+公式)
- hdu 3117 Fibonacci Numbers 数学 矩阵快速幂
- HDU 3117 Fibonacci Numbers(斐波那契数列通项+矩阵快速幂)
- uva11582Colossal Fibonacci Numbers!(快速幂+预处理)
- 【矩阵快速幂】Fibonacci
- Fibonacci 矩阵快速幂
- Fibonacci 矩阵快速幂
- Fibonacci (矩阵快速幂)
- Fibonacci 快速幂矩阵
- poj - 3070 - Fibonacci(矩阵快速幂)
- hdu1588 Gauss Fibonacci (矩阵快速幂)
- poj 3070 Fibonacci(矩阵快速幂)
- Groovy & Grails系列目录
- [福州三中NOIP模拟赛]女装
- 位向量法输出所有子集
- Groovy系列目录
- C#中索引器的详细介绍
- HDU3317---Fibonacci Numbers(矩阵快速幂+pow+log)
- Java IO复习
- Jenkins+SVN+tomcat+Batch Command(Java web项目打包部署运行)
- The Closeable, Flushable, Readable, and Appendable interfaces
- 第十九周(Minimum Number of Arrows to Burst Balloons)
- 【PAT甲级】1077. Kuchiguse (20)
- VC 通过mshtml.dll获取ie版本号
- tesseract-ocr
- 《Hadoop生态》——第二章 数据库与数据管理——HBase