http://acm.hdu.edu.cn/showproblem.php?pid=3117

fib是有一个数学公式的。

这里的是标准的fib公式

那么fib = 1 / sqrt(5) * ((1 + sqrt(5) / 2) ^ n - ((1 - sqrt(5)) / 2)^n) = 1 / sqrt(5) * (A^n - B^n)

那么,求后4位可以直接矩阵快速幂。

不能用上面公式的快速幂取模,因为存在精度误差。

然后求前4位的话,就是一个套路公式了。

在上一篇博客。http://www.cnblogs.com/liuweimingcprogram/p/6583154.html

这里因为后面的B很小,所以可以忽略。如果不忽略的话,就没办法做了。

比如你取A得前4位,减去B的前4位,那肯定错。比如123456789的前4位是1234,而1234的前4位又是1234,那么相减就等于0了。不过这里B的小数,前4位也是0.

然后还要除以sqrt(5),这个时候就需要你保留前5位,除以sqrt(5)后,再保留4位。

不然的话,比如你取了前4位是1234,除以sqrt(5),只剩下3位了。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = ;
struct Matrix {
LL a[maxn][maxn];
int row;
int col;
};
struct Matrix matrix_mul (struct Matrix a, struct Matrix b, int MOD) { //求解矩阵a*b%MOD
struct Matrix c = {}; //这个要多次用到,栈分配问题,maxn不能开太大,
//LL的时候更加是,空间是maxn*maxn的,这样时间用得很多,4和5相差300ms
c.row = a.row; //行等于第一个矩阵的行
c.col = b.col; //列等于第二个矩阵的列
for (int i = ; i <= a.row; i++) { //枚举第一个矩阵的行
for (int j = ; j <= b.col; j++) { //枚举第二个矩阵的列,其实和上面数值一样
for (int k = ; k <= b.row; k++) { //b中的一列中,有“行”个元素 notice
c.a[i][j] += a.a[i][k] * b.a[k][j]; //这里不及时取模,又有可能错!HDU 4565
}
c.a[i][j] = (c.a[i][j] + MOD) % MOD; //如果怕出现了负数取模的话。可以这样做
}
}
return c;
}
struct Matrix quick_matrix_pow(struct Matrix ans, struct Matrix base, int n, int MOD) {
//求解a*b^n%MOD
while (n) {
if (n & ) {
ans = matrix_mul(ans, base, MOD);//传数组不能乱传,不满足交换律
}
n >>= ;
base = matrix_mul(base, base, MOD);
}
return ans;
}
LL fib[];
void init() {
fib[] = ;
fib[] = ;
for (int i = ; i <= ; ++i) {
fib[i] = fib[i - ] + fib[i - ];
}
}
int n;
int calc(double a, LL b, int k) { //a^b的前k + 1位
double res = b * log10(a * 1.0) - (LL)(b * log10(a * 1.0)); //获得小数部分
return (int)(pow(10.0, k + res) / sqrt(5.0));
} int getMost() {
double a = ( + sqrt(5.0)) / ;
int res = calc(a, n, );
while (res >= ) res /= ;
return res;
}
int getLow() {
struct Matrix t1 = {};
t1.row = , t1.col = ;
t1.a[][] = , t1.a[][] = ; struct Matrix t2 = {};
t2.row = t2.col = ;
t2.a[][] = t2.a[][] = ;
t2.a[][] = , t2.a[][] = ; struct Matrix res = quick_matrix_pow(t1, t2, n - , );
return res.a[][];
}
void work() {
if (n <= ) {
cout << fib[n] << endl;
return;
}
int most = getMost();
int low = getLow();
printf("%04d...%04d\n", most, low);
}
int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
init();
while (cin >> n) work();
return ;
}

HDU 3117 Fibonacci Numbers 数学的更多相关文章

  1. HDU 3117 Fibonacci Numbers(围绕四个租赁斐波那契,通过计++乘坐高速动力矩阵)

    HDU 3117 Fibonacci Numbers(斐波那契前后四位,打表+取对+矩阵高速幂) ACM 题目地址:HDU 3117 Fibonacci Numbers 题意:  求第n个斐波那契数的 ...

  2. hdu 3117 Fibonacci Numbers 矩阵快速幂+公式

    斐波那契数列后四位可以用快速幂取模(模10000)算出.前四位要用公式推 HDU 3117 Fibonacci Numbers(矩阵快速幂+公式) f(n)=(((1+√5)/2)^n+((1-√5) ...

  3. HDU 3117 Fibonacci Numbers(矩阵)

    Fibonacci Numbers [题目链接]Fibonacci Numbers [题目类型]矩阵 &题解: 后4位是矩阵快速幂求,前4位是用log加Fibonacci通项公式求,详见上一篇 ...

  4. HDU 3117 Fibonacci Numbers( 矩阵快速幂 + 数学推导 )

    链接:传送门 题意:给一个 n ,输出 Fibonacci 数列第 n 项,如果第 n 项的位数 >= 8 位则按照 前4位 + ... + 后4位的格式输出 思路: n < 40时位数不 ...

  5. hdu 3117 Fibonacci Numbers

    这道题其实也是水题来的,求Fibonacci数的前4位和后4位,在n==40这里分界开.后4位不难求,因为n达到了10^18的规模,所以只能用矩阵快速幂来求了,但在输出后4位的时候一定要注意前导0的处 ...

  6. UVA 11582 Colossal Fibonacci Numbers(数学)

    Colossal Fibonacci Numbers 想先说下最近的状态吧,已经考完试了,这个暑假也应该是最后刷题的暑假了,打完今年acm就应该会退了,但是还什么都不会呢? +_+ 所以这个暑假,一定 ...

  7. codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)(两种方法)

    In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 ...

  8. [HDU3117]Fibonacci Numbers

    题目:Fibonacci Numbers 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3117 分析: 1)后四位可以用矩阵快速幂解决.$T= \left ...

  9. hdu Interesting Fibonacci

    Interesting Fibonacci Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

随机推荐

  1. void类型和void *指针类型(网上摘抄总结)【转】

    http://www.blogjava.net/fhtdy2004/archive/2009/07/09/286004.html 现在在学linux编程过程中遇到很多void *指针类型,由于c很早学 ...

  2. ML assignment #1

    ML assignment #1 Problem: implement classification model to train the Iris dataset and make predicti ...

  3. 编程模式(schema) —— 表驱动法(table-driven)

    使用表驱动法,而非繁琐冗长的 if/else, switch case(本身也代表一种代码坏味道),也是替身编程质量的重要手段, 表驱动法是一种编程模式(schema)-- 从表里面查找信息而不使用逻 ...

  4. js跳转方式 【转】

    第一种:    <script language="javascript" type="text/javascript">           wi ...

  5. nginx开发_Filter模块执行顺序

    Filter模块执行顺序 Filter模块的执行顺序是在执行configure文件时决定的,configure文件执行完成后生成objs/ngx_modules.c,文件中定义了一个数组ngx_mod ...

  6. 非旋treap套线段树

    BZOJ3065. 去年用pascal 块链过了.. 今年来试了试非旋treap大法   注定被块链完爆 代码留这. 第一份 :辣鸡的  垃圾回收做法  跑得极慢 #include <bits/ ...

  7. synergy的配置使用

    1.http://blog.csdn.net/qq_16618179/article/details/54094636 2.两个版本要一致 3.synergy  fail to connect sec ...

  8. 第一行代码笔记的思维导图(http://images2015.cnblogs.com/blog/1089110/201704/1089110-20170413160323298-819915364.png)

  9. HDU 1143 Tri Tiling 递归问题

    将一个3*n的矩形用1*2的矩形填充,n为奇数时一定不能被填满,n*3%2==1 接下来处理这个问题我们要从简单的情况开始考虑,所谓递归就是要能将问题的规模不断减小,通过小问题的解决最后将复杂问题解决 ...

  10. Linux系统启动全过程

    分为两部分,第一部分是硬件本身需要加载的信息,之后才是加载Linux相关信息,因为有装有双系统的机器嘛 1.计算机加电 2.BIOS开始运行,检测硬件:cpu.内存.硬盘等 3.BIOS读取CMOS存 ...