矩陣快速冪(共軛函式)
阿新 • • 發佈:2018-11-11
題目連結: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; }