当给定p,q,r时,我们可以定义
对于给定的p,q,r,n,请计算
对于p=2 q=2 r=1 n=1这组数据,
所以答案是
Input
共1行,4个整数数p, q, r, n中间用空格分隔(1 <= p, q, r, n<=1000000000)。
Output
对于每一个数据,在一行中输出答案。
Input示例
2 2 1 1
Output示例
3
写数学题千万不能偷懒,这道题我开始一直有点懵逼,后来我把叠加式写出了f(n-1)=a<0>*b<n-1>+a<1>*b<n-2>+...+a<n-1>*b<0>。
f(n)=a<0>*b<n>+a<1>*b<n-1>+...+a<n-1>*b<1>+a<n>*b<0>
逐一对比发现f(n)除了最后一项,其他项是f(n-1)*q可以得来,题目上有公式。
然后f(n)=q*f(n-1)+a<n>*b<0>。我就直接用这个公式写了,还写了下矩阵快速幂,先求an再求f(n)...然后答案出奇的大,正确的写法是把an的公式带入f(n),得到f(n)=q*f(n-1)+a<n-1>*p*b<0>+b<n>*r。对比俩公式会发现如果用第一个每次乘的都是an,而第二个公式是从a1开始计算的。有了公式就更好说,矩阵快速幂就好了。
不过写关系矩阵的时候别只看f(n)也要看an的关系式。
f(n-1) a<n-1> r
q 0 0
3q p 0
3 1 1
f(n) a<n> r
f(n)用f(n)的关系式求得关系矩阵,an用an的关系式求关系矩阵
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
const ll mod=1e9+7;
ll p,r,q;
struct mat
{
ll mm[5][5];
};
mat operator*(mat a,mat b)
{
mat c;
memset(c.mm,0,sizeof(c.mm));
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<3;k++)
{
c.mm[i][j]+=(a.mm[i][k]*b.mm[k][j])%mod;
c.mm[i][j]=c.mm[i][j]%mod;
}
}
}
return c;
}
void poww(ll nn)
{
mat ans,res;
memset(ans.mm,0,sizeof(ans.mm));
memset(res.mm,0,sizeof(res.mm));
res.mm[0][0]=q;
res.mm[1][0]=3*p%mod;
res.mm[1][1]=p;
res.mm[2][0]=3;
res.mm[2][1]=1;
res.mm[2][2]=1;
ans.mm[0][0]=0;
ans.mm[0][1]=0;
ans.mm[0][2]=r;
while(nn)
{
if(nn%2==1)
ans=ans*res;
res=res*res;
nn/=2;
}
printf("%lld\n",ans.mm[0][0]%mod);
}
int main()
{
ll n;
while(~scanf("%lld%lld%lld%lld",&p,&q,&r,&n))
{
poww(n);
// ll sum=pow(n);
// printf("%lld\n",sum);
}
}