AT1733Accumulation
問題文
うなぎはクリスマスにサンタうさぎから数列 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)。然后等差数列求和。嗯就这样 咕咕咕
ありがとうございます。