• AT1733Accumulation


    AT1733Accumulation

    洛谷链接
    ATcoder

    問題文

    うなぎはクリスマスにサンタうさぎから数列 S={S1,S2,…,SN} をもらいました。

    うなぎは数列に含まれる数の総和を求めてみることにしました。

    数列 S は、以下のような疑似コードで生成されるものです。

    input N
    input X,T,A,B,C
    for i = 1…N:
    Si = X
    for j = 1…T:
    X=(A*X+B) mod C

    翻译

    对序列S求和。

    序列S由以下伪代码给出:

    input n;
    input x,T,A,B,C;
    for(i~n)
    {
    s[i] = x;
    for(j~t)
    x = (A * x + B) % C;
    }
    输出序列S的各项之和。

    咋做?

    这可以用矩阵乘法

    提前通过矩阵乘法把A,B算一下,这样x之乘算后的A,B,(O(n))计算即可。

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    int n, x, t, a, b, p;
    struct node
    {
        int a[2][2];
        node() {}
        node(bool t)
        {
            memset(a, 0, sizeof a);
            if (t)
                a[1][1] = a[0][0] = 1;
        }
        friend node operator*(const node &a, const node &b)
        {
            node res(0);
            for (register int i = 0; i <= 1; ++i)
                for (register int j = 0; j <= 1; ++j)
                    for (register int k = 0; k <= 1; ++k)
                        (res.a[i][j] += (a.a[i][k] * b.a[k][j]) % p) %= p;
            return res;
        }
        inline void out()
        {
            for (register int i = 0; i <= 1; ++i)
            {
                for (register int j = 0; j <= 1; ++j)
                    cerr << a[i][j] << " ";
                cerr << endl;
            }
        }
    } A, B;
    template <typename T>
    inline T pow(T a, int b)
    {
        node res(1);
        for (; b; b >>= 1)
        {
            if (b & 1)
                res = res * a;
            a = a * a;
        }
        return res;
    }
    signed main()
    {
        cin >> n >> x >> t >> a >> b >> p;
        A.a[0][0] = a;
        A.a[1][0] = b;
        A.a[1][1] = 1;
        A = pow(A, t);
        // A.out();
        a = A.a[0][0];
        b = A.a[1][0];
        int ans = 0;
        for (register int i = 1; i <= n; ++i)
        {
            ans += x;
            x = (a * x + b) % p;
        }
        cout << ans << endl;
    }
    

    siilhouette大佬提供了一个优秀的想法,通过式子推导可以得到(x = A^T + B * displaystyle sum _{i = 0} ^{i leq T}A^i)。然后等差数列求和。嗯就这样 咕咕咕

    ありがとうございます。

  • 相关阅读:
    OC-内存管理-基本原理与引用计数器
    OC-改错题
    OC-Q&A
    OC-SEL
    CO-类的本质、description方法
    Tomcat 下 mysql的连接池配置和使用
    转:JAVA.NET.SOCKETEXCEPTION: TOO MANY OPEN FILES解决方法
    使应用程序常驻内存,不能被任务管理器关闭之配置文件设置
    解决Tomcat catalina.out 不断成长导致档案过大的问题
    >/dev/null 2>&1的含义
  • 原文地址:https://www.cnblogs.com/Shiina-Rikka/p/11586572.html
Copyright © 2020-2023  润新知