矩阵快速幂(共轭函数)

题目链接:https://cn.vjudge.net/contest/261339#problem/A

具体思路:一开始看到这个题,觉得用快速幂就能很简单的求出来,结果发现,要是想用快速幂的话,每次计算必然会损失一定的精度,并且取余的时候必须进行强制转换,所以这个方法绝对不行。

然后就开始想用矩阵快速幂,然后死活推不出公式来,然后看了网上的思路,果然不是一般人能想出来的。

首选观看数据范围,(a-1)^2< b < a ^2,所以  0 < (a- sqrt(b)) < 1,所以这就是一个很好的辅助工具,因为题目中说的是向下取余,具体的作用后面说。  令 A(n)= ( a + sqrt(b) ) ^ n,B(n) = (a - sqrt(b) ) ^ n,也就是说,B是A的共轭函数,然后因为数据范围的原因,我们就可以近似认为B(n)为0. 令 C( n )= A(n) + B(n) 。所以C(n)近似等于A(n)。然后开始推公式。(这是大神的手写)

 

c(n)=a(n)+b(n)=a(n)

c(n)*((a+sqrt(b))+(a-sqrt(b))=c(n+1)+(a*a-b)*c(n-1).这样矩阵就构造出来了。

{ 2*a    b-a*a  }

{1             0     }

AC代码:

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<stdio.h>
#include<iomanip>
#include<algorithm>
using namespace std;
# define ll long long
ll a,b,n,m;
struct Matrix
{
    ll ai[5][5];
    Matrix operator *(Matrix temp)
    {
        Matrix ti;
        for(int i=1; i<=2; i++)
        {
            for(int j=1; j<=2; j++)
            {
                ti.ai[i][j]=0;
                for(int k=1; k<=2; k++)
                {
                    ti.ai[i][j]+=(ai[i][k]%m)*(temp.ai[k][j]%m)%m;
                    ti.ai[i][j]%=m;
                }
            }
        }
        return ti;
    }
};
ll quickpow(Matrix ti,ll t2)
{
    Matrix temp=ti;
    t2--;
    while(t2)
    {
        if(t2&1)temp=temp*ti;
        ti=ti*ti;
        t2>>=1;
    }
    return (temp.ai[1][1]*2*a%m+temp.ai[1][2]*2%m+m)%m;
}
int main()
{
    while(~scanf("%lld%lld%lld%lld",&a,&b,&n,&m))
    {
        Matrix temp;
        temp.ai[1][1]=2*a%m;
        temp.ai[1][2]=(b-a*a%m)%m;
        temp.ai[2][1]=1;
        temp.ai[2][2]=0;
        ll w=2*a%m;
        if(n==1)printf("%lld\n",w);
        else{
        ll ans=quickpow(temp,n-1)%m;
        printf("%lld\n",ans);
        }
    }
    return 0;
}

 

posted @ 2018-10-12 19:00  Let_Life_Stop  阅读(363)  评论(0编辑  收藏  举报