51nod 1341 混合序列(矩阵快速幂)

当给定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);
    }
}

猜你喜欢

转载自blog.csdn.net/zezzezzez/article/details/80411840
今日推荐