矩阵快速幂(共轭函数)
题目链接: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;
}