题目大意
题目链接:http://acm.nit.net.cn/showproblem.jsp?pid=1019
求第n个斐波那契数列对m求余的值。
题目分析
题目类型:矩阵乘法、分治、数据结构。
题目分析:n可能很大,而且不知道m是多少,F(n)可能超过64位,所以不能先储存好再算。同样如果每次输入一次都计算一次的话,计算次数会很多,会超时。这是就想到斐波那契数列的另一种表现形式:矩阵形式。这样完成了加法到乘法的转变,但是速度还没优化。这时想到一个O(log(n))算法:分治,这样时间就不会超,题目就解决了。
通过代码
- # include "stdio.h"
- int m;
- typedef struct
- {
- int r11,r12,r21,r22;
- }mue;
- mue mul(mue a,mue b)
- {
- mue c;
- c.r11=(a.r11*b.r11+a.r12*b.r21)%m;
- c.r12=(a.r11*b.r12+a.r12*b.r22)%m;
- c.r21=(a.r21*b.r11+a.r22*b.r21)%m;
- c.r22=(a.r21*b.r12+a.r22*b.r22)%m;
- return c;
- }
- mue fib(mue a,int n)
- {
- mue r;
- if(n==0) { r.r11=1,r.r12=0,r.r21=0,r.r22=1; return r;}
- if(n==1) { return a;}
- if(n%2) { return mul(fib(mul(a,a),n/2),a);}
- else return fib(mul(a,a),n/2);
- }
- int main ()
- {
- int n;
- while(scanf("%d%d",&n,&m)!=-1)
- {
- mue r;
- r.r11=1,r.r12=1,r.r21=1,r.r22=0;
- r=fib(r,n-1);
- printf("%d/n",r.r11);
- }
- return 0;
- }