zoukankan      html  css  js  c++  java
  • 2019 南昌 ICPC网络赛 H The Nth Item (矩阵快速幂/二次剩余+记忆化)

    题目连接

    原题描述

    For a series:

    egin{gathered} F(0) = 0,F(1) = 1\ F(n) = 3*F(n-1)+2*F(n-2),(n geq 2) end{gathered}F(0)=0,F(1)=1F(n)=3F(n1)+2F(n2),(n2)

    We have some queries. For each query NN, the answer AA is the value F(N)F(N) modulo 998244353998244353.

    Moreover, the input data is given in the form of encryption, only the number of queries QQ and the first query N_1N1 are given. For the others, the query N_i(2leq ileq Q)Ni(2iQ) is defined as the xor of the previous N_{i-1}Ni1 and the square of the previous answer A_{i-1}Ai1. For example, if the first query N_1N1 is 22, the answer A_1A1 is 33, then the second query N_2N2 is 2 xor ( 3*3)=112 xor (33)=11.

    Finally, you don't need to output all the answers for every query, you just need to output the xor of each query's answer A_1 xor A_2 ... xor A_QA1 xor A2...xor AQ.

    Input

    The input contains two integers, Q, NQ,N, 1 leq Q leq 10^7,0 leq N leq 10^{18}1  Q107,0  N1018. QQ representing the number of queries and NN representing the first query.

    Output

    An integer representing the final answer.

    Solution

    题目中的式子$F(n)=3*F(n-1)+2*F(n-2),ngeq 2$是一个二阶常系数线性递推式,可以用特征方程求解通项

    $特征方程为:x^2-3x-2=0,x_1=frac{3+sqrt{17}}{2},x_2=frac{3-sqrt{17}}{2},令F(n)=c_1{x_1}^n+c_2{x_2}^n$

    $代入F(0)=0,F(1)=1,c_1=frac{sqrt{17}}{17},c_2=-c_1$

    $得出式子$ $$F(n)=frac{sqrt{17}}{17}[{(frac{3+sqrt{17}}{2})}^n-{(frac{3-sqrt{17}}{2})}^n]$$

    好的到了这里我就没了,并不会二次剩余,然后我开始莽,写了一发矩阵快速幂+unordered_map记忆化

    !!!就过了,xswl

    #include <algorithm>
    #include <cctype>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #if __cplusplus >= 201103L
    #include <unordered_map>
    #include <unordered_set>
    #endif
    #include <vector>
    #define lson rt << 1, l, mid
    #define rson rt << 1 | 1, mid + 1, r
    #define LONG_LONG_MAX 9223372036854775807LL
    #define ll LL
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair<int, int> P;
    int n, m, k;
    const int maxn = 1e5 + 10;
    const int mod = 998244353;
    template <class T>
    inline T read()
    {
        int f = 1;
        T ret = 0;
        char ch = getchar();
        while (!isdigit(ch))
        {
            if (ch == '-')
                f = -1;
            ch = getchar();
        }
        while (isdigit(ch))
        {
            ret = (ret << 1) + (ret << 3) + ch - '0';
            ch = getchar();
        }
        ret *= f;
        return ret;
    }
    template <class T>
    inline void write(T n)
    {
        if (n < 0)
        {
            putchar('-');
            n = -n;
        }
        if (n >= 10)
        {
            write(n / 10);
        }
        putchar(n % 10 + '0');
    }
    template <class T>
    inline void writeln(const T &n)
    {
        write(n);
        puts("");
    }
    struct mat
    {
        ll tmp[2][2];
        mat()
        {
            for (int i = 0; i < 2; i++)
                for (int j = 0; j < 2; j++)
                    tmp[i][j] = 0;
        }
    };
    mat mul(const mat &a, const mat &b)
    {
        mat res;
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                for (int k = 0; k < 2; k++)
                    res.tmp[i][j] = (res.tmp[i][j] + a.tmp[i][k] * b.tmp[k][j] % mod) % mod;
        return res;
    }
    mat qpow(mat a, ll n)
    {
        mat res;
        res.tmp[0][0] = res.tmp[1][1] = 1;
        while (n)
        {
            if (n & 1)
                res = mul(res, a);
            a = mul(a, a);
            n >>= 1;
        }
        return res;
    }
    unordered_map<ll, ll> mp;
    inline ll cal(ll n)
    {
        if (mp.count(n))
            return mp[n];
        mat m;
        m.tmp[0][0] = 3, m.tmp[0][1] = 2;
        m.tmp[1][0] = 1;
        m = qpow(m, n - 1);
        return mp[n] = m.tmp[0][0] % mod;
    }
    void init()
    {
        ll a = 0, b = 1;
        for (int i = 0; i < 1e6; i++)
        {
            mp[i] = a;
            ll t = b;
            b = (3 * b % mod + 2 * a % mod) % mod;
            a = t;
        }
    }
    int main(int argc, char const *argv[])
    {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    #endif
        init();
        ll n = read<ll>(), q = read<ll>();
        ll pre = q, res = 0, tres = 0;
        for (int i = 0; i < n; i++)
        {
            pre ^= (tres * tres);
            tres = cal(pre);
            res ^= tres;
        }
        writeln(res);
        return 0;
    }
    矩阵快速幂+unordered_map记忆化

    $赛后看了题解,了解了一点点二次剩余,于是回到上面推出的通项公式$

    $先求出 sqrt{17} 在模998244353意义下的二次剩余sqrt{17}=473844410,以及inv(sqrt{17})=559329360 $

    $将其代入F(n)得到$

    $$F(n)=559329360*(262199973^n-736044383^n)$$

    题解后续优化菜鸡没看明白,来日再更。得到上式加了一个记忆化也过了,不过计蒜客看不了运行时间qaq

    #include <algorithm>
    #include <cctype>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #if __cplusplus >= 201103L
    #include <unordered_map>
    #include <unordered_set>
    #endif
    #include <vector>
    #define lson rt << 1, l, mid
    #define rson rt << 1 | 1, mid + 1, r
    #define LONG_LONG_MAX 9223372036854775807LL
    #define ll LL
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair<int, int> P;
    int n, m, k;
    const int maxn = 1e5 + 10;
    const int mod = 998244353;
    template <class T>
    inline T read()
    {
        int f = 1;
        T ret = 0;
        char ch = getchar();
        while (!isdigit(ch))
        {
            if (ch == '-')
                f = -1;
            ch = getchar();
        }
        while (isdigit(ch))
        {
            ret = (ret << 1) + (ret << 3) + ch - '0';
            ch = getchar();
        }
        ret *= f;
        return ret;
    }
    template <class T>
    inline void write(T n)
    {
        if (n < 0)
        {
            putchar('-');
            n = -n;
        }
        if (n >= 10)
        {
            write(n / 10);
        }
        putchar(n % 10 + '0');
    }
    template <class T>
    inline void writeln(const T &n)
    {
        write(n);
        puts("");
    }
    ll qpow(ll a, ll b)
    {
        ll res = 1;
        while (b)
        {
            if (b & 1)
                res = res * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return res;
    }
    struct num
    {
        ll x, y;
    };
    ll w;
    num mul(num a, num b, ll p)
    {
        num ans = {0, 0};
        ans.x = ((a.x * b.x % p + a.y * b.y % p * w % p) % p + p) % p;
        ans.y = ((a.x * b.y % p + a.y * b.x % p) % p + p) % p;
        return ans;
    }
    
    ll powwR(ll a, ll b, ll p)
    {
        ll ans = 1;
        while (b)
        {
            if (b & 1)
                ans = 1ll * ans % p * a % p;
            a = a % p * a % p;
            b >>= 1;
        }
        return ans % p;
    }
    ll powwi(num a, ll b, ll p)
    {
        num ans = {1, 0};
        while (b)
        {
            if (b & 1)
                ans = mul(ans, a, p);
            a = mul(a, a, p);
            b >>= 1;
        }
        return ans.x % p;
    }
    
    ll solve(ll n, ll p)
    {
        n %= p;
        if (p == 2)
            return n;
        if (powwR(n, (p - 1) / 2, p) == p - 1)
            return -1; //不存在
        ll a;
        while (1)
        {
            a = rand() % p;
            w = ((a * a % p - n) % p + p) % p;
            if (powwR(w, (p - 1) / 2, p) == p - 1)
                break;
        }
        num x = {a, 1};
        return powwi(x, (p + 1) / 2, p);
    }
    const ll p1 = 262199973, p2 = 736044383;
    const ll sqrt17 = 473844410, invsqrt17 = 559329360;
    unordered_map<ll, ll> mp;
    ll cal(ll n)
    {
        if (mp.count(n))
            return mp[n];
        return mp[n] = (qpow(p1, n) - qpow(p2, n) + mod) % mod * invsqrt17 % mod;
    }
    int main(int argc, char const *argv[])
    {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        // freopen("out.txt", "w", stdout);
    #endif
        srand(time(0));
        int q = read<int>();
        ll n = read<ll>();
        ll pre = 0, res = 0;
        for (int i = 0; i < q; i++)
        {
            n ^= (pre * pre);
            pre = cal(n);
            res ^= pre;
        }
        writeln(res);
        return 0;
    }
    二次剩余+unordered_map

    广义斐波那契循环节。。upt

    
    


  • 相关阅读:
    linux下执行python错误: bad interpreter: No such file or directory
    linux下修改默认python版本
    MySQL 远程连接配置的正确实现
    Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 7
    通达信软件快捷键
    MT4快捷键
    vim快捷键
    Linux5.5下配置Centos的yum源
    ls命令结果中文件夹颜色(蓝色)的改变方法
    rest-framework之响应器(渲染器)
  • 原文地址:https://www.cnblogs.com/mooleetzi/p/11492237.html
Copyright © 2011-2022 走看看