斐波那契

来源:互联网 发布:淘宝苹果组装机 编辑:程序博客网 时间:2024/04/30 12:50

转自:http://www.aichengxu.com/cyvyan/17027.htm

问题描述

斐波那契数列大家都非常熟悉。它的定义是:

f(x) = 1 .... (x=1,2)
f(x) = f(x-1) + f(x-2) .... (x>2)

对于给定的整数 n 和 m,我们希望求出:

f(1) + f(2) + ... + f(n) 的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
公式如下

(Σ(1,n)f(i))%f(m)
但这个数字依然很大,所以需要再对 p 求模。

输入格式

输入为一行用空格分开的整数 n m p (0 < n, m, p < 10^18)

输出格式

输出为1个整数,表示答案

分析

这道题需要考虑斐波那契数列的多个性质。

性质1:Σ(1,n-2)f(i)=f(n)-1

证明:f(1)=f(3)-1,∴f(1)+f(2)=f(3)+f(2)-1=f(4)-1

以此类推,f(1)+f(2)+…+f(n-2)=f(n)-1

性质2:f(n+i)%f(n)=[f(i)*f(n-1)]%f(n) ,i>=1

证明:f(n+1)%f(n)=(f(n)+f(n-1))%f(n)=f(n-1)=f(1)*f(n-1)

f(n+2)%f(n)=(2f(n)+f(n-1))%f(n)=f(n-1)=f(2)*f(n-1)

……

f(n+i)%f(n)=(f(n+i-1)+f(n+i-2))%f(n)=[f(i)*f(n-1)]%f(n)

有了上述两个性质,题目就可以进行一些简化。

当n>=m时,原式=[f(m)-1 + f(m-1) + f(m) + f(m-1)*Σ(1,n-m)f(i)]%f(m)

=[f(m-1)*f(n-m+2)-1]%f(m)

当m=n+1时,原式=[f(m)-1 + f(m-1)]%f(m)=f(m-1)-1

当m>n+1时,原式=f(n+2)-1


问题描述
  斐波那契数列大家都非常熟悉。它的定义是:

  f(x) = 1 .... (x=1,2)
  f(x) = f(x-1) + f(x-2) .... (x>2)

  对于给定的整数 n 和 m,我们希望求出:
  f(1) + f(2) + ... + f(n) 的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
  公式如下


  但这个数字依然很大,所以需要再对 p 求模。
输入格式
  输入为一行用空格分开的整数 n m p (0 < n, m, p < 10^18)
输出格式
  输出为1个整数,表示答案
样例输入
2 3 5
样例输出
0
样例输入
15 11 29
样例输出
25

#include <iostream>

#include <cstdio>#include <cstring>#include <cstdlib>#define LENGTH 20000using namespace std;__int64 n,m,p;int f[65][2][2][LENGTH];bool check[65];int answ[LENGTH];int parray[LENGTH];int getlen(int *array){    int cnt=0;    while(array[cnt]!=-1)        cnt++;    return cnt;}int *getmod(int* ,int*);void print(int *array){    int i;    int para[LENGTH];    memcpy(para,array,sizeof(para));    int res[LENGTH];    memcpy(res,getmod(para,parray),sizeof(res));    int len = getlen(res);    for(i=len-1;i>=0;i--)        printf("%d",res[i]);}int compare(int *m1,int *m2){    int l1=getlen(m1);    int l2=getlen(m2);    if(l1>l2)         return 1;    else if(l1<l2)    return -1;    else{        for(int i=l1-1;i>=0;i--)            if(m1[i]>m2[i])     return 1;            else if(m1[i]<m2[i])       return -1;        return 0;    }}void l2str(){    int i=0;    memset(parray,-1,sizeof(parray));    while(p)    {        parray[i++] = p%10;        p/=10;      }}void init(){    memset(f,-1,sizeof(f));    memset(check,false,sizeof(check));    f[0][0][0][0]=1;    f[0][0][1][0]=0;    f[0][1][0][0]=0;    f[0][1][1][0]=1;    f[1][0][0][0]=0;    f[1][0][1][0]=1;    f[1][1][0][0]=1;    f[1][1][1][0]=1;    check[0]=check[1]=true;}void add(int *m1,int *m2){    int len1=getlen(m1);    int len2=getlen(m2);    int i;    int c=0;for(i=len1;i<len2;i++)m1[i]=0;if(len1<len2)len1=len2;    for(i=0;i<len2;i++)    {        m1[i] = m1[i]+m2[i]+c;        if(m1[i]>=10)        {            m1[i]-=10;            c=1;        }        else            c=0;    }    for(;i<len1;i++)    {        if(c==0)    break;        m1[i]++;        if(m1[i]>=10) m1[i]-=10;        else c=0;    }    if(i==len1 && c==1)        m1[len1]=1;}void subtract(int *m1,int *m2){    int len1=getlen(m1);    int len2=getlen(m2);    int i;    int c=0;    for(i=0;i<len2;i++)    {        m1[i] = m1[i]-m2[i]-c;        if(m1[i]<0)        {            m1[i]+=10;            c=1;        }        else            c=0;    }    for(;i<len1;i++)    {        if(c==0)    break;        m1[i] -= c;        if(m1[i]<0) m1[i]+=10;        else break;    }    i=len1-1;    while(i>=0 && m1[i]==0)    {        m1[i]=-1;        i--;    }    if(i==-1)        m1[0]=0;}void multiply(int *m1,int *m2){    int len1=getlen(m1);    int len2=getlen(m2);    int i,j,c;    memset(answ,0,sizeof(answ));    for(i=0;i<len2;i++)    {        c=0;        for(j=0;j<len1;j++)        {            answ[i+j] += (m1[j]*m2[i]+c);            c = answ[i+j]/10;            answ[i+j]%=10;        }        while(c)        {            answ[i+j]=c%10;            j++;            c/=10;        }    }    i=LENGTH-1;    while(i>=0 && answ[i]==0)    {        answ[i]=-1;        i--;    }if(i==-1)answ[0]=0;}int *getmod(int *m1,int *m2){    int i,j;    int *remainder=(int *)malloc(LENGTH*sizeof(int));    //memset(remainder,-1,sizeof(remainder));    for(i=0;i<LENGTH;i++)        remainder[i]=-1;    int len=0,len1=getlen(m1),len2=getlen(m2);    for(i=0;i<len1;i++)    {for(j=len-1;j>=0;j--)remainder[j+1]=remainder[j];        remainder[0]=m1[len1-i-1];len++;        while((len>len2) || (len==len2 && compare(remainder,m2)>=0))        {            subtract(remainder,m2);            len=getlen(remainder);        }            }    if(getlen(remainder)==0)        remainder[0]=0;    return remainder;}void mulMatrix(int m1[2][2][LENGTH],int m2[2][2][LENGTH]){    int t[2][2][LENGTH];    memcpy(t,m1,sizeof(t));    int array[LENGTH];multiply(t[0][0],m2[0][0]);    memcpy(array,answ,sizeof(array));multiply(t[0][1],m2[1][0]);    add(array,answ);    memcpy(m1[0][0],array,sizeof(m1[0][0]));multiply(t[0][0],m2[0][1]);memcpy(array,answ,sizeof(array));multiply(t[0][1],m2[1][1]);    add(array,answ);    memcpy(m1[0][1],array,sizeof(m1[0][1]));multiply(t[1][0],m2[0][0]);    memcpy(array,answ,sizeof(array));multiply(t[1][1],m2[1][0]);    add(array,answ);    memcpy(m1[1][0],array,sizeof(m1[1][0]));    multiply(t[1][0],m2[0][1]);memcpy(array,answ,sizeof(array));multiply(t[1][1],m2[1][1]);    add(array,answ);    memcpy(m1[1][1],array,sizeof(m1[1][1]));}int *fabonacci(__int64 num){    int matrix[2][2][LENGTH];    memset(matrix,-1,sizeof(matrix));    matrix[0][0][0]=1;    matrix[0][1][0]=0;    matrix[1][0][0]=0;    matrix[1][1][0]=1;    num--;    int pos=1;    while(num)    {        if(num%2)        {            mulMatrix(matrix,f[pos]);        }        num/=2;        pos++;        if(num)        {            if(!check[pos])            {                memcpy(f[pos],f[pos-1],sizeof(f[pos]));                mulMatrix(f[pos],f[pos-1]);                check[pos]=true;            }            }    }    return matrix[1][1];}int main(){    freopen("data.txt","r",stdin);    freopen("answer.txt","w",stdout);    init();    int temp[LENGTH];    memset(temp,-1,sizeof(temp));    temp[0]=1;    scanf("%I64d%I64d%I64d",&n,&m,&p);    l2str();    int *pt;int a[LENGTH],b[LENGTH];    if(n>=m)    {memcpy(a,fabonacci(m-1),sizeof(a));memcpy(b,fabonacci(n-m+2),sizeof(b));        multiply(a,b);memcpy(b,answ,sizeof(b));        subtract(b,temp);memcpy(a,fabonacci(m),sizeof(a));pt=getmod(b,a);    }    else if(m==n+1)    {        memcpy(a,fabonacci(m-1),sizeof(a));        pt = a;        subtract(pt,temp);    }    else    {memcpy(a,fabonacci(n+2),sizeof(a));        pt = a;        subtract(pt,temp);    }    print(pt);return 0;}

Thinking:
设f(i)为斐波那契数列第i项,s(i)=f(1)+f(2)+...+f(i),
  i  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15
f(i) 1  1  2  3  5  8 13 21 34  55  89  144 233 377 610
s(i) 1  2  4  7 12 20 33 54 88 143 232  376 609 ... ...
观察发现:
s(i)=f(i+2)-1 (i>0)
又:
s(i)%f(m)=(f(i+2)-1)%f(m)
 =f(i+2)%f(m)+f(m)-1
 =(f(i)+f(i+1))%f(m)+f(m)-1;
得到公式之后就好办多了,但是有一个问题,n,m,p的范围较大,必须用大整数+快速幂运算才能得满分

0 0
原创粉丝点击