1. 程式人生 > 實用技巧 >F - Problem of Precision

F - Problem of Precision

HDU - 2256

神仙題,完全沒想到。

樸素想法,我們開4*4的矩陣,分別記錄\(\sqrt{2}\),\(\sqrt{3}\),\(\sqrt{6}\),\(1\)的係數,然後快速冪。

但是我們沒法對係數取模,因此不能確定整數部分。

再分析一下,題目讓我們求\((\sqrt{2} + \sqrt{3})^{2n}\),那不就是\((5 + 2\sqrt{6})^{n}\)嗎,這成功減少了一個無理數,我們繼續用剛才的方法。

雖然依舊不能算出答案,但是矩陣只要2*2了。

接下來就是我不會的東西了

考慮上面的矩陣,我們可以利用它來求得準確解\(a+b\sqrt{6}\),其中\(a\)可以準確知道,並在計算過程中取模

採用數學方法消去\(b\sqrt{6}\),我們構造\((5-2\sqrt{6})^n\),其準確值為\(a-b\sqrt{6}\)

\((5+2\sqrt{6})^n + (5-2\sqrt{6})^n = a+b\sqrt{6}+a-b\sqrt{6}=2a\)

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

\(t = (5-2\sqrt{6})^n\)\(\lfloor (5+2\sqrt{6})^n \rfloor = \lfloor 2a - t \rfloor = 2a - 1\)

利用矩陣乘法計算\(a\)

即可

其實可以類似複數定義一種數為\(x+y\sqrt{6}\),直接算乘法。


#include<bits/stdc++.h>
using namespace std;

const int mod =  1024;

struct node{
    long long a,b;
};
node operator * (node x,node y){
    node c; 
    c.a = (x.a * y.a % mod + x.b * y.b % mod * 6 % mod ) % mod;
    c.b = (x.a * y.b % mod + x.b * y.a % mod ) % mod;
    return c;
}
node ksm(node x,int y){
    node z; z.a = 1; z.b = 0;
    while(y){
        if(y & 1) z = z * x;
        y >>= 1;
        x = x * x;
    }
    return z;
}

int main(){
    int T; scanf("%d",&T);
    while(T --){
        int n; scanf("%d",&n);
        node x; x.a = 5; x.b = 2;
        node y; y.a = 5; y.b = -2;
        x = ksm(x,n); y = ksm(y,n);
        long long ans = (x.a + y.a) % mod;
        ans = (ans - 1 + mod) % mod;
        printf("%lld\n",ans);
    }
    return 0;
}