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)。然后等差数列求和。嗯就这样 咕咕咕

ありがとうございます。

原文地址:https://www.cnblogs.com/Shiina-Rikka/p/11586572.html