zoukankan      html  css  js  c++  java
  • bzoj5104 Fib数列

    bzoj5104 Fib数列

    求在模 (10^9+9) 的意义下 (n) 在斐波那契数列中出现的最小位置,无解输出 (-1)

    (n<10^9+9)


    由于 (sqrt5) 在模 (10^9+9) 的意义下的二次剩余为 (383008016) ,因此可以将 (sqrt5) 带入斐波那契数列的通项公式

    (y=frac{1+sqrt5}{2})

    即求最小的 (x) 满足 $$frac{yx-(frac{-1}{y})x}{sqrt5}equiv npmod {10^9+9}$$

    化一下式子,得到 $$yx+(-1){x+1}frac{1}{y^x}equivsqrt5npmod {10^9+9}$$

    (t=y^x) ,原式可以看作为一个二元一次方程 (t^2-sqrt5nt+(-1)^{n+1}=0)

    于是 分类讨论 (n) 的奇偶,暴力带入求根公式, (Delta) 用二次剩余计算,即可求出 (t)

    现在的问题就变成了求 (y^xequiv tpmod{10^9+9}) ,BSGS 即可

    时间复杂度 (O(sqrt nlog n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int P = 1e9 + 9, inv_2 = 500000005, sqrt_5 = 383008016;
    int N, omg;
    
    inline int inc(int x, int y) {
      return x + y < P ? x + y : x + y - P;
    }
    
    struct domain {
      int x, y;
    
      domain() {}
      domain(int _x, int _y) :
        x(_x), y(_y) {}
    
      inline domain operator + (const domain &o) const {
        return domain(inc(x, o.x), inc(y, o.y));
      }
    
      inline domain operator * (const domain &o) const {
        return domain((1ll * x * o.x + 1ll * y * o.y % P * omg) % P, (1ll * x * o.y + 1ll * y * o.x) % P);
      }
    };
    
    inline int rnd() {
      return (rand() << 15 | rand()) % P;
    }
    
    inline int qp(int a, int k) {
      int res = 1;
      for (; k; k >>= 1, a = 1ll * a * a % P) {
        if (k & 1) res = 1ll * res * a % P;
      }
      return res;
    }
    
    inline domain qp(domain a, int k) {
      domain res = domain(1, 0);
      for (; k; k >>= 1, a = a * a) {
        if (k & 1) res = res * a;
      }
      return res;
    }
    
    int Cipolla(int n) {
      int k = (P - 1) >> 1;
      if (qp(n, k) == -1) {
        return -1;
      }
      int a = rnd();
      while (qp((1ll * a * a - n + P) % P, k) == 1) {
        a = rnd();
      }
      omg = (1ll * a * a - n + P) % P;
      return qp(domain(a, 1), k + 1).x;
    }
    
    int BSGS(int a, int b) {
      if (!a && b) return -1;
      map <int, int> s;
      int sz = sqrt(P), inv_a = qp(a, P - 2);
      for (int i = 0, cur = 1; i <= sz; i++) {
        s.insert(make_pair(1ll * b * cur % P, i)), cur = 1ll * cur * inv_a % P;
      }
      int pw = qp(a, sz);
      map <int, int> :: iterator it;
      for (int i = 0, cur = 1; i <= sz; i++, cur = 1ll * cur * pw % P) {
        if ((it = s.find(cur)) != s.end()) {
          return i * sz + (it -> second);
        }
      }
      return -1;
    }
    
    signed main() {
      srand(time(0));
      scanf("%d", &N);
      int x = 1ll * N * sqrt_5 % P;
      int y = 1ll * (sqrt_5 + 1) * inv_2 % P;
      int delta, tmp, res, ans = INT_MAX;
      delta = Cipolla((1ll * x * x - 4 + P) % P);
      if (~delta) {
        tmp = 1ll * (x + delta) * inv_2 % P, res = BSGS(y, tmp);
        if (~res && res & 1) ans = min(ans, res);
        tmp = 1ll * (x - delta + P) * inv_2 % P, res = BSGS(y, tmp);
        if (~res && res & 1) ans = min(ans, res);
      }
      delta = Cipolla((1ll * x * x + 4) % P);
      if (~delta) {
        tmp = 1ll * (x + delta) * inv_2 % P, res = BSGS(y, tmp);
        if (~res && ~res & 1) ans = min(ans, res);
        tmp = 1ll * (x - delta + P) * inv_2 % P, res = BSGS(y, tmp);
        if (~res && ~res & 1) ans = min(ans, res);
      }
      printf("%d", ans < INT_MAX ? ans : -1);
      return 0;
    }
    
  • 相关阅读:
    淘宝技术分享
    15个富有创意的单页设计
    jQuery全能图片滚动插件
    jquery性能优化
    Algs4-1.4.40随机输入3-sum问题
    Algs4-1.4.39 改进倍率测试的精度
    Algs4-1.4.38 3-sum的初级算法与ThreeSum性能比较
    Algs4-1.4.37自动装箱的性能代价
    Algs4-1.4.35下压栈的时间成本
    Algs4-1.4.36下压栈的空间成本
  • 原文地址:https://www.cnblogs.com/Juanzhang/p/10821996.html
Copyright © 2011-2022 走看看