hdu 1568求斐波那契数的前4位 && hdu3117矩阵快速幂
2017-07-19 09:48
337 查看
hdu1568
斐波那契数的通项式为:1 / sqrt(5.0) * (((1 + sqrt(5.0)/2)/2)^n - (sqrt(1 - sqrt(5.0))/2))^n)
一开始就知道要取对数,但怎么也没想到后面的大一点的时候可以省掉,zz.
假设给出一个数10234432,那么log10(10234432)=log10(1.0234432*10^7)=log10(1.0234432)+7;
log10(1.0234432)就是log10(10234432)的小数部分.
log10(1.0234432)=0.010063744
10^0.010063744=1.023443198
那么要取几位就很明显了吧~
先取对数(对10取),然后得到结果的小数部分bit,pow(10.0,bit)以后如果答案还是<1000那么就一直乘10。
注意偶先处理了0~20项是为了方便处理~
这题要利用到数列的公式:an=(1/√5) * [((1+√5)/2)^n-((1-√5)/2)^n](n=1,2,3.....)
取完对数
log10(an)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0)+log10(1-((1-√5)/(1+√5))^n)其中f=(sqrt(5.0)+1.0)/2.0;
log10(1-((1-√5)/(1+√5))^n)->0
所以可以写成log10(an)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0);
最后取其小数部分。
hdu3117取前四位和取后四位,取前四位与上题一样,去后四位的时候矩阵快速幂,不过要注意当不足的时候补零。如123430011,前四位和后四位分别是1234 ,0011,
因为这个补零,错了好几次。
斐波那契数的通项式为:1 / sqrt(5.0) * (((1 + sqrt(5.0)/2)/2)^n - (sqrt(1 - sqrt(5.0))/2))^n)
一开始就知道要取对数,但怎么也没想到后面的大一点的时候可以省掉,zz.
假设给出一个数10234432,那么log10(10234432)=log10(1.0234432*10^7)=log10(1.0234432)+7;
log10(1.0234432)就是log10(10234432)的小数部分.
log10(1.0234432)=0.010063744
10^0.010063744=1.023443198
那么要取几位就很明显了吧~
先取对数(对10取),然后得到结果的小数部分bit,pow(10.0,bit)以后如果答案还是<1000那么就一直乘10。
注意偶先处理了0~20项是为了方便处理~
这题要利用到数列的公式:an=(1/√5) * [((1+√5)/2)^n-((1-√5)/2)^n](n=1,2,3.....)
取完对数
log10(an)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0)+log10(1-((1-√5)/(1+√5))^n)其中f=(sqrt(5.0)+1.0)/2.0;
log10(1-((1-√5)/(1+√5))^n)->0
所以可以写成log10(an)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0);
最后取其小数部分。
#include<bits/stdc++.h> using namespace std; const int maxn = 100 + 10; int f[maxn]; void Init() { f[0] = 0;f[1] = 1; for(int i = 2; i <= 20; i ++) f[i] = f[i - 1] + f[i - 2]; } int main() { Init(); int n; while( ~ scanf("%d",&n)) { if(n <= 20) { cout << f << endl;continue; } double temp = -0.5 * log10(5.0) + n * log10((1 + sqrt(5.0))/2); temp -= floor(temp); temp = pow(10,temp); while(temp < 1000) temp *= 10; printf("%d\n",(int)temp); } return 0; }
hdu3117取前四位和取后四位,取前四位与上题一样,去后四位的时候矩阵快速幂,不过要注意当不足的时候补零。如123430011,前四位和后四位分别是1234 ,0011,
因为这个补零,错了好几次。
#include<bits/stdc++.h> using namespace std; const int maxn = 100 + 10; int f[maxn]; void Init() { f[0] = 0;f[1] = 1; for(int i = 2; i <= 39; i ++) f[i] = f[i - 1] + f[i - 2]; } struct Matrix { Matrix(){memset(m,0,sizeof(m));} int m[2][2]; }; Matrix p; Matrix Mul(Matrix a,Matrix b) { Matrix c; for(int i = 0;i < 2; i ++) { for(int j = 0; j < 2; j ++) { c.m[i][j] = 0; for(int k = 0; k < 2; k ++) c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j] % 10000) % 10000; } } return c; } int pow_mod(Matrix p,int n) { Matrix ret;ret.m[0][0] = ret.m[1][1] = 1; Matrix x = p; while(n) { if(n & 1) ret = Mul(ret,x); n >>= 1; x = Mul(x,x); } return ret.m[0][0]; } int main() { Init(); int n; while( ~ scanf("%d",&n)) { p.m[0][0] = p.m[0][1] = p.m[1][0] = 1; if(n <= 39) { cout << f << endl;continue; } double temp = -0.5 * log10(5.0) + n * log10((1 + sqrt(5.0))/2); temp -= floor(temp); temp = pow(10,temp); while(temp < 1000) temp *= 10; int t = pow_mod(p,n - 1); printf("%d...%04d\n",(int)temp,t); } return 0; }
相关文章推荐
- hdu 1098 Ignatius's puzzle
- hdu 2732 && poj 2711 Leapin' Lizards(dinic && 拆点建图经典)
- 【HDU 6070 Dirt Ratio】 二分 & 线段树
- hdu 1505 && hdu1506 &&hdu 2830 && 2870 总结---------DP之状图选最大矩形
- HDU 4791 Alice's Print Service 水二分
- SPOJ 5152 Brute-force Algorithm EXTREME && HDU 3221 Brute-force Algorithm 快速幂,快速求斐波那契数列,欧拉函数,同余 难度:1
- hdu 1568
- hdu 1556 Color the ball&&hdu 4883 TIANKENG’s restaurant
- hdu Yukari's Birthday (4430)
- HDU 3376 && HDU 2686 Matrix
- hdu——2603——Wiskey's Power
- hdu 5642 King's Order 递推
- hdu 1160 FatMouse's Speed( 最长下降子序列 )
- HDU - 1098 - Ignatius's puzzle (数论 - 费马小定理)
- HDU 1009 FatMouse' Trade(贪心)
- Coins (poj 1742 && hdu 2844 DP)
- hdu 1568关于斐波那契数列的公式及其思维技巧
- HDU 5349 MZL's simple problem(平衡树 树堆)
- HDU-1012-u Calculate e( C++ && 2000年纽约水果)
- zhx's contest (hdu 5187 快速幂+快速乘法)