hdu 3117 Fibonacci Numbers 数学 矩阵快速幂
2015-11-04 21:02
363 查看
题目
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3117题目来源:随便兜到的。
简要题意:求斐波那契第nn项,大于八位输出前后四位。
数据范围:0⩽n⩽1080\leqslant n \leqslant 10^8
题解
首先斐波那契足够大了之后fibx≈ϕfibx−1fib_x\approx \phi fib_{x-1}其中ϕ=1+5√2\phi=\frac{1+\sqrt{5}}{2},也就是黄金数。取3939为足够大则fibx=fib39⋅ϕn−39fib_x={fib_{39}\cdot \phi^{n-39}}
令bit=log10fib39+(n−39)⋅log10ϕbit = \log_{10}{fib_{39}}+(n-39)\cdot \log_{10}\phi
则fibx=10bitfib_x=10^{bit}其位数为⌊bit⌋\lfloor bit \rfloor
前四位就是10bit/10⌊bit⌋−3=10bit−⌊bit⌋+310^{bit}/10^{\lfloor bit \rfloor -3}=10^{bit-\lfloor bit \rfloor +3}
后四位的话矩阵快速幂递推就行了,好像也有做法是找循环节的。
实现
这类题实现的话要用log10这个函数比较好,不然会容易被卡掉精度。代码
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <queue> #include <string> #include <vector> #include <set> #include <map> #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define sz(x) ((int)(x).size()) #define fi first #define se second using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;} // head int fib[55]; double phi = (1.0+sqrt(5.0))/2; const int N = 2; const LL MOD = 10000; struct Matrix { LL grid ; int row, col; Matrix() { row = col = N; memset(grid, 0, sizeof(grid)); } Matrix operator *(const Matrix &b); Matrix operator ^(int exp); void setSize(int row, int col) { this->row = row, this->col = col; } void setValue(int row, int col, LL val) { grid[row][col] = val; } void clear() { memset(grid, 0, sizeof(grid)); } LL getValue(int row, int col) { return grid[row][col]; } }; Matrix Matrix::operator *(const Matrix &b) { Matrix res; res.setSize(row, b.col); for (int i = 0; i < res.row; i++) { for (int j = 0; j < res.col; j++) { for (int k = 0; k < col; k++) res.grid[i][j] = (res.grid[i][j] + (grid[i][k] * b.grid[k][j]) % MOD + MOD) % MOD; } } return res; } Matrix Matrix::operator ^(int exp) { Matrix res, temp; for (int i = 0; i < N; i++) res.grid[i][i] = 1; temp = *this; while (exp > 0) { if (exp & 1) res = temp * res; exp >>= 1; temp = temp * temp; } return res; } int getFib(int n) { Matrix init, trans; init.setSize(1, 2); init.setValue(0, 1, 1); trans.setValue(0, 1, 1); trans.setValue(1, 0, 1); trans.setValue(1, 1, 1); init = init*(trans^n); return init.getValue(0, 0); } int main() { fib[1] = 1; for (int i = 2; i <= 39; i++) { fib[i] = fib[i-1]+fib[i-2]; } int n; while (scanf("%d", &n) == 1) { if (n < 40) { printf("%d\n", fib ); continue; } double x = log10(fib[39])+(n-39)*log10(phi); printf("%d...", (int)pow(10, x-(floor(x)-3))); printf("%04d\n", getFib(n)); } return 0; }
相关文章推荐
- 安装java和Eclipse
- oracle 新建用户
- swift中的字符串的一些运用
- 采药
- 计算几何 专题
- [python]在WingIDE中创建flask项目
- MFC——属性页对话框的创建
- 不积跬步无以至千里-2
- 软件文档概述(一)
- 在AngularJs中怎么设置请求头信息(headers)及不同方法的比较
- thinkphp解决表单令牌问题
- web.xml 通过contextConfigLocation配spring 的方式
- EM-期望最大化算法
- 黑马程序员—Java基础—IO4
- win7/9/10 U盘启动盘的制作
- uiautomator使用
- c++成员函数指针
- October——I Will Talk
- 修改了系统自带头文件后,Xcode会报错
- 第三节:欠拟合与过拟合的概念