HDU----(4549)M斐波那契数列(小费马引理+快速矩阵幂)
M斐波那契数列
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1534 Accepted Submission(s): 435
Problem Description
M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗?
Input
输入包含多组测试数据; 每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )
Output
对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行。
Sample Input
01 0
6 10 2
Sample Output
0 60
Source
F[n] = F[n-1] * F[n-2] ---》 F[n] = F[n-2]^2* F[n-3]^1----》F[n] = F[n-3]^3* F[n-4]^2----》
F[n] = F[n-4]^5* F[n-5]^3 -----......--->F[n] = F[2]^a[n-1]* F[1]^a[n-2]; //我们可以的到处a[n]为一个斐波那契数列
但是对于这样一个式子:
F[n] = F[2]^a[n-1]* F[1]^a[n-2]; 我们依旧还是不好处理哇,毕竟n<1e9这么大,这样我们不妨引用小费马引理处理....
首先我们应该知道小费马引理的定义:
形如: (a^b)mod c = a^(b mod (c-1) ) mod c;
这样,我们就可以找到这样一个方法来做这道题:
F[n] = F[2]^a[n-1]* F[1]^a[n-2]; 可以写成 F[n] = (F[2]^(a[n-1]%(mod-1))* F[1]^(a[n-2]%(mod-1)))%mod;
可以明确的是,F[2],F[1]我们事先已经知道,所以问题在于求解a[n-1],a[n-2]由于数据巨大,为了提升效率我们可以使用矩阵快速幂来求解
对于 a[n]=a[n-1]+a[n-2] a[0]=a[1]=1; 这样的斐波那契数列,我们应该不难构造出它的矩阵来
|a[n] | =|1,1|^(n-2) |a[n-1]|
|a[n-1]| |1,0|* |a[n-2]|
得到了 a[n],a[n-1]之后我们在使用一个快速幂求解 a^b 即可。
代码:
1 //#define LOCAL
2 #include<iostream>
3 #include<cstdio>
4 #include<cstring>
5 #define LL __int64
6 using namespace std;
7 const int mod =1000000007;
8
9 LL mat[2][2];
10 LL ans[2][2];
11 LL n,aa,bb;
12
13 void Matrix(LL a[][2],LL b[][2])
14 {
15 LL cc[2][2]={0};
16 for(int i=0;i<2;i++)
17 {
18 for(int j=0;j<2;j++)
19 {
20 for(int k=0;k<2;k++)
21 {
22 cc[i][j]=(cc[i][j]+a[i][k]*b[k][j])%(mod-1);
23 }
24 }
25 }
26 for(int i=0;i<2;i++)
27 {
28 for(int j=0;j<2;j++)
29 {
30 a[i][j]=cc[i][j];
31 }
32 }
33 }
34
35 void pow(LL w)
36 {
37 mat[1][1]=mat[0][1]=mat[1][0]=1;
38 mat[0][0]=0;
39
40 while(w>0)
41 {
42 if(w&1) Matrix(ans,mat);
43 w>>=1;
44 if(w==0)break;
45 Matrix(mat,mat);
46 }
47 }
48 LL pow_int(LL a,LL b)
49 {
50 LL ans=1;
51 while(b>0)
52 {
53 if(b&1){
54 ans*=a;
55 ans%=mod;
56 }
57 b>>=1;
58 if(b==0)break;
59 a*=a;
60 a%=mod;
61 }
62 return ans;
63 }
64 void input(LL w)
65 {
66 ans[0][0]=ans[1][1]=1;
67 ans[0][1]=ans[1][0]=0;
68 pow(w-2);
69 LL fn_2=(ans[0][0]+ans[0][1])%(mod-1);
70 pow(1);
71 LL fn_1=(ans[0][0]+ans[0][1])%(mod-1);
72 printf("%I64dn",(pow_int(aa,fn_2)*pow_int(bb,fn_1))%mod);
73 }
74
75 int main()
76 {
77 #ifdef LOCAL
78 freopen("test.in","r",stdin);
79 #endif
80 while(scanf("%I64d%I64d%I64d",&aa,&bb,&n)!=EOF)
81 if(n==0)printf("%I64dn",aa);
82 else if(n==1)printf("%I64dn",bb);
83 else
84 input(n);
85 return 0;
86 }
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 文件操作——举例
- flink之udf执行流程分析篇
- VBA调用外部对象02:FileSystemObject——操作文本文件
- 打卡群刷题总结0723——组合
- VBA根据单元格底色统计个数
- 打卡群刷题总结0724——子集
- 打卡群刷题总结0726——删除排序数组中的重复项 II
- VBA调用外部对象02:FileSystemObject——OpenTextFile参数
- 使用HTTP 404-File Not Found的C2
- MySQL主从复制详解
- Excel VBA事件——ActiveX控件
- Excel VBA事件
- VBA调用外部对象02:FileSystemObject——其他函数
- 递归的理解
- Excel VBA事件——Worksheet