hdu 3509 Buge's Fibonacci Number Problem(矩阵乘法+二项式)

来源:互联网 发布:redis数据库 编辑:程序博客网 时间:2024/05/21 14:49

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3509

Buge's Fibonacci Number Problem

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 726    Accepted Submission(s): 205


Problem Description
snowingsea is having Buge’s discrete mathematics lesson, Buge is now talking about the Fibonacci Number. As a bright student, snowingsea, of course, takes it as a piece of cake. He feels boring and soon comes over drowsy.
Buge,feels unhappy about him, he knocked at snowingsea’s head, says:”Go to solve the problem on the blackboard!”, snowingsea suddenly wakes up, sees the blackboard written :



snowingsea thinks a moment,and writes down:



snowingsea has a glance at Buge,Buge smiles without talking, he just makes a little modification on the original problem, then it becomes :



The modified problem makes snowingsea nervous, and he doesn't know how to solve it. By the way,Buge is famous for failing students, if snowingsea cannot solve it properly, Buge is very likely to fail snowingsea. But snowingsea has many ACM friends. So,snowingsea is asking the brilliant ACMers for help. Can you help him?

 

Input
The input consists of several test cases. The first line contains an integer T representing the number of test cases. Each test case contains 7 integers, they are f1, f2, a, b, k, n, m which were just mentioned above, where 0 < f1, f2, a, b, n, m < 1000 000 000, and 0 ≤ k < 50.

 

Output
For each case, you should print just one line, which contains S(n,k) %m.
 

Sample Input
31 1 1 1 1 2 1000001 1 1 1 1 3 1000001 1 1 1 1 4 100000
 

Sample Output
247
 

Source
2010 ACM-ICPC Multi-University Training Contest(8)——Host by ECNU
 
分析:
首先我们知道有这样的定理:

接下来,看一个阶数不大的例子,当k=3时:

写成矩阵的形式:

啊,这里出现了麻烦,等号右边矩阵f前面有a,b系数时会让它的展开式变得非常的难看,这样很难看出规律。那么干脆矩阵里就写f不带a,b,于是成为:

嗯,是的,只带上f。右边是s[n-1]没关系。接下来就是编码。矩阵连乘和二项式构造。很快速的敲完,结果交了N次才过,为什么!!??最后发现是取模——"%m",每一步都不能忽略!仔细!!
#include <iostream>#include <cstdio>#include <cstring>using namespace std;typedef long long LL;struct matrie{    LL m[60][60];};matrie A,I;void pascal(LL k){    for(LL i=1;i<k+2;i++){        A.m[i][k+1]=1;        A.m[i][k+2-i]=1;    }    for(LL i=1;i<k+2;i++){        for(LL j=k+3-i;j<k+1;j++){            A.m[i][j]=A.m[i-1][j]+A.m[i-1][j+1];        }    }}LL pow(LL a,LL p,LL mod){    LL ans=1;    a=a%mod;    while(p--) ans=ans*a%mod;    return ans;}void getab(LL a,LL b,LL mod,LL k){    for(LL i=2;i<k+2;i++){        for(LL j=k+2-i;j<k+2;j++){            A.m[i][j]=(A.m[i][j]%mod)*pow(a,j-(k+2-i),mod)%mod*pow(b,i-1-j+(k+2-i),mod);            A.m[i][j]%=mod;        }    }}matrie multi(matrie a,matrie b,LL len,LL mod){    matrie c;    for(LL i=0;i<len;i++){        for(LL j=0;j<len;j++){            c.m[i][j]=0;            for(LL k=0;k<len;k++){                c.m[i][j]+=((a.m[i][k]%mod)*(b.m[k][j]%mod))%mod;  //here ?  no                c.m[i][j]%=mod;            }        }    }    return c;}matrie quick_mod(LL n,LL len,LL mod){  // LL ? no    matrie res=I,temp=A;    while(n){        if(n&1) res=multi(res,temp,len,mod);        temp=multi(temp,temp,len,mod);        n>>=1;    }    return res;}LL quick(LL a,LL p,LL mod){    LL res=1,temp=a%mod;    while(p){        if(p&1)res=res*temp%mod;        temp=temp*temp%mod;        p>>=1;    }    return res;}void init(){    for(LL i=0;i<60;i++)        for(LL j=0;j<60;j++)A.m[i][j]=0;}void show(int k){    for(int i=0;i<k+2;i++){        for(int j=0;j<k+2;j++)cout<<A.m[i][j]<<" ";        cout<<endl;    }}int main(){    //freopen("cin.txt","r",stdin);    LL t;    cin>>t;    LL f1,f2,a,b,k,n,m;    for(LL i=0;i<60;i++) I.m[i][i]=1;    while(t--){        scanf("%lld %lld %lld %lld %lld %lld %lld",&f1,&f2,&a,&b,&k,&n,&m);        if(k==0){            printf("%lld\n",n%m);            continue;        }        if(n==1){            printf("%lld\n",quick(f1,k,m));              continue;        }        if(n==2){            printf("%lld\n",(quick(f1,k,m)+quick(f2,k,m))%m);            continue;        }        init();        A.m[0][0]=A.m[0][k+1]=1;        pascal(k);        getab(a,b,m,k);        A=quick_mod(n-1,k+2,m);        //show(k);        LL ans=0;        ans=(A.m[0][0]%m)*quick(f1,k,m)%m;        for(LL i=1;i<k+2;i++){            ans=ans+((A.m[0][i]%m)*pow(f2,i-1,m)%m*pow(f1,k-i+1,m))%m;            ans=ans%m;        }        printf("%lld\n",ans);    }    return 0;}



0 0