/*
    题意: 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