BZOJ5104 Fib数列 二次剩余、BSGS

传送门


发现只有通项公式可以解决考虑通项公式

\(F_n = \frac{1}{\sqrt{5}}((\frac{1+\sqrt{5}}{2})^n - (\frac{1-\sqrt{5}}{2})^n) = a\)

注意到根据二次互反律,在\(\mod 10^9+9\)意义下\(5\)存在二次剩余,所以先把\(\sqrt{5}\)对应的值算出来(实际上是\(383001016\))。

那么原式变为了\((\frac{1+\sqrt{5}}{2})^n - (\frac{1-\sqrt{5}}{2})^n = \sqrt{5}a\)\(x^n-y^n=a\)的方程好像还是不会解TAT

观察上面式子可以发现:\(\frac{1-\sqrt{5}}{2} = -\frac{1}{\frac{1 + \sqrt{5}}{2}}\),所以设\(\frac{1 + \sqrt{5}}{2} = x\),那么原式变为\(x - \frac{(-1)^n}{x} = \sqrt{5}a\)

按照\(n\)的奇偶性讨论,可以得到一个一元二次方程,使用求根公式求出方程的解。注意到在求根公式中还有一个求\(\sqrt{\Delta}\)的操作,这里还需要计算一次二次剩余,如果这里二次剩余无解,那么方程就是无解的,否则就存在两个解。

然后我们最后的问题就是解出\((\frac{1 + \sqrt{5}}{2})^n = t\)的最小的\(n\),同时需要满足\(n\)是奇数或者是偶数。这里我们同样使用BSGS,只需要在分块的时候把块大小分成偶数,然后对于奇数和偶数分开考虑就可以了。

#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
using namespace std::tr1;
 
const int MOD = 1e9 + 9;
int val , g , sqrt5 , inv2;
 
int poww(long long a , int b){
    int times = 1;
    while(b){
        if(b & 1) times = times * a % MOD;
        a = a * a % MOD; b >>= 1;
    }
    return times;
}
 
struct BSGS{
    unordered_map < int , int > odd , even , all;
    int T , powbs;
     
    void init(int base){
        T = sqrt(MOD) + 1; if(T & 1) ++T;
        powbs = poww(base , T);
        int tms = 1;
        for(int i = 0 ; i < T ; ++i , tms = 1ll * tms * base % MOD){
            unordered_map < int , int > &now = i & 1 ? odd : even;
            now[tms] = i; all[tms] = i;
        }
    }
     
    int calc(int ans , int val){
        unordered_map < int , int > &now = val == 0 ? all : (val == 1 ? odd : even);
        int tms = 1ll * powbs * poww(ans , MOD - 2) % MOD;
        for(int i = 1 ; i <= T ; ++i , tms = 1ll * tms * powbs % MOD)
            if(now.find(tms) != now.end())
                return i * T - now[tms];
        return 2e9 + 1;
    }
}A , B;
 
int findrt(){
    int t = MOD - 1; vector < int > zys;
    for(int i = 2 ; i * i <= t ; ++i)
        if(t % i == 0){
            zys.push_back(MOD / i);
            while(t % i == 0) t /= i;
        }
    if(t - 1) zys.push_back(MOD / t);
    for(int i = 2 ; ; ++i){
        bool flg = 1;
        for(int j = 0 ; j < zys.size() && flg ; ++j)
            if(poww(i , zys[j]) == 1) flg = 0;
        if(flg) return i;
    }
}
 
int main(){
    cin >> val; g = findrt(); A.init(g); sqrt5 = poww(g , A.calc(5 , 0) / 2);
    val = 1ll * val * sqrt5 % MOD; inv2 = poww(2 , MOD - 2);
    B.init((1ll + sqrt5) * inv2 % MOD);
     
    int t = A.calc((1ll * val * val + MOD - 4) % MOD , 0) , ans = 2e9 + 1;
    if(t % 2 == 0){
        int sqt = poww(g , t / 2) , ans1 = 1ll * (val + sqt) * inv2 % MOD , ans2 = 1ll * (val - sqt + MOD) * inv2 % MOD;
        ans = min(B.calc(ans1 , 1) , B.calc(ans2 , 1));
    }
 
    t = A.calc((1ll * val * val + 4) % MOD , 0);
    if(t % 2 == 0){
        int sqt = poww(g , t / 2) , ans1 = 1ll * (val + sqt) * inv2 % MOD , ans2 = 1ll * (val - sqt + MOD) * inv2 % MOD;
        ans = min(ans , min(B.calc(ans1 , 2) , B.calc(ans2 , 2)));
    }
 
    if(ans == 2e9 + 1) puts("-1");
    else cout << ans;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Itst/p/11104904.html
fib