这题也可以用矩阵快速幂来轻松解决,但是在比赛的时候没有构造出矩阵,然后直接用数学的方法把这题ac了,方法如下:
可以得出an和bn都是类等比数列,类等比数列暂且定义为等比数列之间的加减乘除组合后的数列,an,bn如下:
an=A0*Ax^n+Ay*(Ax^(n-1)+Ax^(n-2)+……+Ax^1+Ax^0).(n>=1)
bn=B0*Bx^n+By*(Bx^(n-1)+Bx^(n-2)+……+Bx^1+Bx^0).(n>=1)
令Fn=an*bn,所以Fn也是类等比数列;
然后sum{Fn}就是一些等比数列求和的问题了,等比数列求和可以用公式的快速幂+逆元实现;
不过在这里还要注意一下Ax和Bx等于1和0的情况,因为当Ax和Bx等于1时就变成了等差数列,当为0时就变成了常数列,
任何数列和常数列相乘性质不变,等差和等比数列相乘我们可以用错位相减的方法求解,这个方法记得在高中做数学题时经常用到;
具体的推导公式就不一一列出了,反正有好一大坨;
代码如下(15~31ms):
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include<bitset>
#include<string>
#include<queue>
#include<deque>
#include<ctype.h>
#include<vector>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<functional>
#include<algorithm>
using namespace std;
#define mod 1000000007
long long mult(long long x,long long y){
long long sum=0;
while(y){
if(y&1) sum=(sum+x)%mod;
x=(x+x)%mod;
y>>=1;
}
return sum;
}
long long power(long long x,long long y){
long long sum=1;x%=mod;
while(y){
if(y&1) sum=(x*sum)%mod;
x=x*x%mod;
y>>=1;
}
return sum;
}
long long caldiff(long long a0,long long a1,long long n){
return mult((a0+a0+mult(a1,n-1))%mod,n)*power(2,mod-2)%mod;
}
long long calratio(long long a0,long long a1,long long n){
long long ans=a0%mod;
ans=ans*((power(a1,n)+mod-1)%mod)%mod;
ans=ans*power(a1-1,mod-2)%mod;
return ans;
}
long long cal2(long long a,long long n){
long long ans=(2*mod-n%mod-1+mult(a,n))%mod;
ans=((ans*power(a,n+1))%mod+a)%mod;
ans=ans*power(a-1,mod-2)%mod*power(a-1,mod-2)%mod;
return ans;
}
int main(){
long long n,A[3],B[3],ans,i,t;
while(scanf("%I64d",&n)!=EOF){
scanf("%I64d%I64d%I64d",&A[0],&A[1],&A[2]);
scanf("%I64d%I64d%I64d",&B[0],&B[1],&B[2]);
if(n==0){
printf("0\n");continue;
}
if(n==1){
ans=A[0]*B[0]%mod;
printf("%d\n",int(ans));
continue;
}
if(A[1]==0&&B[1]==0){
ans=A[2]*B[2]%mod;
ans=mult(ans,n-1);
ans=(ans+(A[0]*B[0])%mod)%mod;
}
else if(A[1]+B[1]==1){
if(B[1]==1)for(i=0;i<3;i++) swap(A[i],B[i]);
ans=A[0]*B[0]%mod;
ans=(ans+mult((A[0]*B[2])%mod,n-1))%mod;
ans=(ans+caldiff(0,A[2]*B[2]%mod,n))%mod;
}
else if(A[1]==1&&B[1]==1){
ans=mult(A[0]*B[0]%mod,n);
ans=(ans+caldiff(0,(B[0]*A[2]%mod+A[0]*B[2]%mod)%mod,n))%mod;
ans=(ans+mult(A[2]*B[2]%mod,mult(mult(n-1,n),2*n-1))*power(6,mod-2))%mod;
}
else if(B[1]==0&&A[1]>1||A[1]==0&&B[1]>1){
if(A[1]==0) for(i=0;i<3;i++) swap(A[i],B[i]);
ans=(A[0]*B[0])%mod;
t=((A[0]*B[2])%mod+B[2]*A[2]%mod*power(A[1]-1,mod-2)%mod)%mod;
ans=(ans+t*calratio(A[1],A[1],n-1)%mod)%mod;
ans=(ans+mod-mult((A[2]*B[2]%mod*power(A[1]-1,mod-2))%mod,n-1))%mod;
}
else if(B[1]==1&&A[1]>1||A[1]==1&&B[1]>1){
if(A[1]==1) for(i=0;i<3;i++) swap(A[i],B[i]);
ans=(A[0]*B[0])%mod;
t=ans+A[2]*B[0]%mod*power(A[1]-1,mod-2)%mod;
ans=(ans+t*calratio(A[1],A[1],n-1)%mod)%mod;
t=(A[0]*B[2]%mod+B[2]*A[2]%mod*power(A[1]-1,mod-2)%mod)%mod;
ans=(ans+t*cal2(A[1],n-1))%mod;
ans=(ans+mod-caldiff(0,A[2]*B[2]%mod*power(A[1]-1,mod-2),n))%mod;
ans=(ans+mod-mult(A[2]*B[0]%mod*power(A[1]-1,mod-2)%mod,n-1))%mod;
}
else {
ans=(A[0]*B[0])%mod;
t=A[0]*B[0]%mod;
t=(t+A[0]*B[2]%mod*power(B[1]-1,mod-2)%mod)%mod;
t=(t+B[0]*A[2]%mod*power(A[1]-1,mod-2)%mod)%mod;
t=(t+A[2]*B[2]%mod*power(A[1]-1,mod-2)%mod*power(B[1]-1,mod-2)%mod)%mod;
ans=(ans+t*calratio(A[1]*B[1]%mod,A[1]*B[1]%mod,n-1)%mod)%mod;
t=(mod-A[0]*B[2]%mod*power(B[1]-1,mod-2)%mod)%mod;
t=(t+mod-A[2]*B[2]%mod*power(A[1]-1,mod-2)%mod*power(B[1]-1,mod-2)%mod)%mod;
ans=(ans+t*calratio(A[1],A[1],n-1)%mod)%mod;
t=(mod-B[0]*A[2]%mod*power(A[1]-1,mod-2)%mod)%mod;
t=(t+mod-A[2]*B[2]%mod*power(A[1]-1,mod-2)%mod*power(B[1]-1,mod-2)%mod)%mod;
ans=(ans+t*calratio(B[1],B[1],n-1)%mod)%mod;
t=A[2]*B[2]%mod*power(A[1]-1,mod-2)%mod*power(B[1]-1,mod-2)%mod;
ans=(ans+mult(t,n-1))%mod;
}
printf("%I64d\n",ans);
}
return 0;
}
版权声明:本文为laziercs原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。