1. 程式人生 > >【矩陣+共軛構造】HDU - 4565 - So Easy!

【矩陣+共軛構造】HDU - 4565 - So Easy!

題目連結<http://acm.hdu.edu.cn/showproblem.php?pid=4565>


題意:

求出:

0< a, m < 215, (a-1)^{2}< b < a^{2}, 0 < b, n < 231


題解:

首先從(a+\sqrt{b})^{n}入手,很容易發現它的構成是X+Y\sqrt b的形式。

假設(a+\sqrt{b})^{n}=X+Y\sqrt b,那麼(a+\sqrt{b})^{n+1}=(X+Y\sqrt b)*(a+\sqrt{b})=(Xa+Yb)+(aY+X)\sqrt b

所以可以構造出矩陣:\begin{pmatrix} a &b \\ 1 &a \end{pmatrix}.

還有一個向上取整的問題,這題利用共軛來構造出答案,否則精度會有問題。

因為(a-1)^{2}< b < a^{2},所以0<a-\sqrt b<1,所以0<(a-\sqrt b)^{n}<1

利用二項式展開可以得出:(a+\sqrt{b})^{n}+(a-\sqrt{b})^{n}=2X,所以2X就是答案。


#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <queue>
#include <map>
#include <cmath>
using namespace std;
typedef long long ll;
ll s[2][2],p[2][2],q[2][2],m;
void mul(ll a[2][2],ll b[2][2]){
    ll c[2][2];
    memset(c,0,sizeof(c));
    for(ll i=0;i<2;i++)
        for(ll j=0;j<2;j++)
            for(ll k=0;k<2;k++)
                c[i][j]=(c[i][j]+a[i][k]*b[k][j])%m;
    memcpy(b,c,sizeof(c));
}
void mpow(ll t){
    for(ll i=t;i;i>>=1,mul(p,p)){
        if(i&1) mul(p,s);
    }
}
int main(){
    ll n,a,b;
    while(scanf("%lld%lld%lld%lld",&a,&b,&n,&m)!=EOF){
        p[0][0]=a;p[0][1]=b;
        p[1][0]=1;p[1][1]=a;
        s[0][0]=a;s[1][0]=1;
        mpow(n-1);
        printf("%lld\n",s[0][0]*2%m);
    }
}