 /**//*
题意: F[n] = a*F[n-1]+b*F[n-2] 求 Sn = ∑F[i]^k
矩阵乘法
Sn = ∑F[i]^k = F[n]^k + Sn-1 = (aF[n-1]+bF[n-2])^k + Sn-1 二项式定理展开
= C(k,0)F[n-1]^kF[n-2]^0 + + C(k,k)F[n-1]^0F[n-2]^k + Sn-1 *
构造向量
T(n-1) = (F[n-1]^kF[n-2]^0 , , F[n-1]^0F[n-2]^k , Sn-1)
则T(n) = (F[n]^kF[n-1]^0 , , F[n]^0F[n-1]^k , Sn)
现在的问题是如何构造出矩阵A,使得 T(n-1)*A = T(n)
由式子*,我们能知道A的最后一列(第K+1列)是(C(k,0) , , C(k,k),1)T

现在剩下的问题是维护向量剩下的那些项,即F[n-1]^xF[n-2]^(k-x)
同样是用二项式定理展开即可,这里不赘述了

*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

long long f1,f2,a,b,K,N,MOD;

long long C[60][60],A[60][60];

long long apow(long long a,long long n)
  {
long long ans = 1;
while(n)
 {
if(n&1)ans=(ans*a)%MOD;
n>>=1;
a=a*a%MOD;
}
return ans;
}
void init()
  {
for(int i=0;i<=K;i++)
C[i][i]=C[i][0]=1;
for(int i=2;i<=K;i++)
for(int j=1;j<i;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
memset(A,0,sizeof(A));
//A[][]
for(int i=0;i<=K;i++)
A[i][K+1]=C[K][i]*apow(a,K-i)%MOD*apow(b,i)%MOD;//乘法时也要%MOD,不然会wa!!!!
A[K+1][K+1]=1;
for(int j=0;j<=K;j++)
for(int i=0;i<=K-j;i++)
A[i][j]=C[K-j][i]*apow(a,K-j-i)%MOD*apow(b,i)%MOD;//A[i,j] = C(K-j,i)*a^(K-j-i)*b^i
}
void mul(long long A[][60],long long B[][60])//A=A*B
  {
 long long R[60][60]= {0};
for(int k=0;k<=K+1;k++)
for(int i=0;i<=K+1;i++)
if(A[i][k])
for(int j=0;j<=K+1;j++)
R[i][j]=(R[i][j]+A[i][k]*B[k][j])%MOD;
for(int i=0;i<=K+1;i++)
for(int j=0;j<=K+1;j++)
A[i][j]=R[i][j];
}
void mpow(long long R[][60],long long n)
  {
if(n==1)
 {
for(int i=0;i<=K+1;i++)
for(int j=0;j<=K+1;j++)
R[i][j]=A[i][j];
return;
}
mpow(R,n/2);
mul(R,R);
if(n&1)mul(R,A);
}
int main()
  {
//freopen("in","r",stdin);
int T;
for(scanf("%d",&T);T--;)
 {
scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&f1,&f2,&a,&b,&K,&N,&MOD);
 if(N==1) {printf("%I64d\n",apow(f1,K));continue;}
long long s2=(apow(f1,K)+apow(f2,K))%MOD;
 if(N==2) {printf("%I64d\n",s2);continue;}
init();
long long R[60][60];
mpow(R,N-2);
long long ans = 0;
for(int i=0;i<=K;i++)
 {
ans=(ans+apow(f2,K-i)*apow(f1,i)%MOD*R[i][K+1])%MOD;
}
ans=(ans+s2*R[K+1][K+1])%MOD;
printf("%I64d\n",ans);
}
return 0;
}
这里也有一道二项式定理的: http://www.cppblog.com/Yuan/archive/2010/08/13/123268.html
|