zoukankan      html  css  js  c++  java
  • 块速幂/光速幂

    最近队友拿来一个蛮有意思的东西

    给定一个类似于斐波那契数列的东西,让你去求它的第(n)((n<=10^{18})),由于模数为1e9+7,可以先降一波幂,相当于(n<=10^9+7),要么去推下特征方程要么矩阵快速幂,但是这题把带log的做法卡了,引出了一个被叫做光速幂的东西,但我感觉叫块速幂更正常点...

    就叫块速幂吧,实际上很简单,如果求(p^q)(p)已经给定,(q)的上限也已经确定是在(1e12)左右或者以下,设(sq=sqrt{q})那么我们线性预处理处理出(p cdots p^{sq}),再处理出(p^{sq},p^{2sq}cdots)

    那看到这个式子应该很显然了(p^q=p^{q/sq}p^{sq}p^{q\%sq})

    对于所有(n<=1e12)的询问我们都能(o(1))计算

    类似板子的东西(这玩意真的有必要存板子么

    struct KSM
    {
        int fac[MAXN];
        int facp[MAXN];
        ll p;               //给定p
        ll maxq = 1e9 + 10; //已知的p的幂次上限(maxq<=1e12)
        int sqrtq;
        void init(ll x)
        {
            sqrtq = int(sqrt(maxq)) + 1;
            p = x;
            //预处理到p^sqrtq
            fac[0] = 1;
            for (int i = 1; i <= sqrtq; i++)
                fac[i] = 1LL * fac[i - 1] * p % MOD;
            //再处理(p^sqtr)^sqtr
            facp[0] = 1;
            for (int i = 1; i <= sqrtq; i++)
                facp[i] = 1LL * facp[i - 1] * fac[sqrtq] % MOD;
        }
        int cal(int x)
        {
            return 1LL * facp[x / sqrtq] * fac[x % sqrtq] % MOD;
        }
    }
    

    队友拿来的那道题

    传送门

    解题过程

    (a_n=233a_{n-1}+666a_{n-2})

    去网上搜下斐波那契通项公式怎么求就知道了

    这种数列基本可以令(a_n=p^n)次将递推公式化成(p^2=233p+666)

    解得(p_1=frac{233+sqrt{56953}}{2}), (p_2=frac{233-sqrt{56953}}{2})

    (A,B)为任意实数,(a_n=Ap_1^n+Bp_2^n)

    (a_1=1,a_2=233)分别代入

    如果把数值一开始带进去除了会受到233和666的毒害以外毫无意义..先把(p_1,p_2)放在里面推一波

    可以得到(B=frac{233-p_1}{p_2(p_2-p_1)},A=frac{233-p_2}{p_1(p_1-p_2)})

    所以(B=frac{frac{233-sqrt{56953}}{2}}{p_2(p_2-p_1)}=frac{p_2}{p_2(p_2-p_1)}=frac{1}{p_2-p_1}=frac{1}{sqrt{56953}})

    同理(A=frac{-1}{sqrt{56953}})

    所以(a_n=frac{(233+sqrt{56953})^n-(233-sqrt{56953})^n}{2^nsqrt{56953}})

    掏出二次剩余板子找到(sqrt{56953})的二次剩余是(188305837)

    所以在膜1e9+7条件下

    (a_n=frac{(frac{233+188305837}{2})^n-(frac{233-188305837}{2})^n}{188305837})

    (=frac{(94153035)^n-(905847205)^n}{188305837})

    好像算好了 还被卡了一手常数

    #include <bits/stdc++.h>
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/hash_policy.hpp>
    #include <ext/pb_ds/tree_policy.hpp>
    #include <ext/pb_ds/trie_policy.hpp>
    using namespace __gnu_pbds;
    using namespace std;
    // freopen("k.in", "r", stdin);
    // freopen("k.out", "w", stdout);
    // clock_t c1 = clock();
    // std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    mt19937 rnd(time(NULL));
    #define de(a) cout << #a << " = " << a << endl
    #define rep(i, a, n) for (int i = a; i <= n; i++)
    #define per(i, a, n) for (int i = n; i >= a; i--)
    #define ls ((x) << 1)
    #define rs ((x) << 1 | 1)
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> PII;
    typedef pair<double, double> PDD;
    typedef pair<char, char> PCC;
    typedef pair<ll, ll> PLL;
    typedef vector<int> VI;
    #define inf 0x3f3f3f3f
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const ll MAXN = 1e5 + 7;
    const ll MAXM = 4e5 + 7;
    const ll MOD = 1e9 + 7;
    const double eps = 1e-7;
    ll qpw(ll a, ll b)
    {
        ll ans = 1;
        while (b)
        {
            if (b & 1)
                ans = (ans * a) % MOD;
            (a *= a) %= MOD;
            b >>= 1;
        }
        return ans;
    }
    struct KSM
    {
        int fac[MAXN];
        int facp[MAXN];
        ll p;               //给定p
        ll maxq = 1e9 + 10; //已知的p的幂次上限(maxq<=1e12)
        int sqrtq;
        void init(ll x)
        {
            sqrtq = int(sqrt(maxq)) + 1;
            p = x;
            //预处理到p^sqrtq
            fac[0] = 1;
            for (int i = 1; i <= sqrtq; i++)
                fac[i] = 1LL * fac[i - 1] * p % MOD;
            //再处理(p^sqtr)^sqtr
            facp[0] = 1;
            for (int i = 1; i <= sqrtq; i++)
                facp[i] = 1LL * facp[i - 1] * fac[sqrtq] % MOD;
        }
        int cal(int x)
        {
            return 1LL * facp[x / sqrtq] * fac[x % sqrtq] % MOD;
        }
    } a, b;
    
    namespace Mker
    {
        unsigned long long SA, SB, SC;
        void init() { scanf("%llu%llu%llu", &SA, &SB, &SC); }
        unsigned long long rand()
        {
            SA ^= SA << 32, SA ^= SA >> 13, SA ^= SA << 1;
            unsigned long long t = SA;
            SA = SB, SB = SC, SC ^= t ^ SA;
            return SC;
        }
    } // namespace Mker
    int del(int a, int b)
    {
        int tmp = a - b;
        if (tmp < 0)
            tmp += MOD;
        return tmp;
    }
    int main()
    {
        int t;
        a.init(94153035), b.init(905847205);
        int inv = qpw(188305837, MOD - 2);
        int ans = 0;
        scanf("%d", &t);
        Mker::init();
        while (t--)
        {
            int n = Mker::rand() % (MOD - 1);
            ans ^= 1LL * del(a.cal(n), b.cal(n)) * inv % MOD;
        }
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    点击其他地方隐藏div
    jquery获得被选中radio的值
    c++几个新特性
    effective c++ (三)
    80X86保护模式及其编程(一)
    Linux内核完全注释之编程语言和环境(二)
    Linux内核完全注释之编程语言和环境(一)
    linux内核完全注释之微型计算机组成结构
    effective c++ (二)
    effective c++ (一)
  • 原文地址:https://www.cnblogs.com/graytido/p/13917063.html
Copyright © 2011-2022 走看看