Forever Young

洛谷 P2044 [NOI2012]随机数生成器

思路

首先,题目中直接给出了递推式,但按照题意直接做肯定是不行的,因为 \(n\) 很大,所以要用矩阵加速,初状态为 \([x_i \ c]\),末状态为 \([x_{i+1} \ c]\),转移矩阵为

\[\begin{bmatrix}x_i&c\end{bmatrix} \times \begin{bmatrix}a&0\\1&1\end{bmatrix}=\begin{bmatrix}x_{i+1}&c\end{bmatrix} \]

注意 \(m\) 很大,做乘法的时候要用快速乘

代码

/*
  Name: P2044 [NOI2012]随机数生成器
  Author: Loceaner
  Date: 02/09/20 15:01
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;

const int A = 1e5 + 11;
const int B = 1e6 + 11;
const int inf = 0x3f3f3f3f;

inline int read() {
  char c = getchar();
  int x = 0, f = 1;
  for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
  for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
  return x * f;
}

int mod, a, c, x0, n, g;

struct matrix {
  int ma[3][3];
  void init() { for (int i = 1; i <= 2; i++) ma[i][i] = 1; }
  void clear() { memset(ma, 0, sizeof(ma)); }
} base, ans;

inline int mul(int a, int b) {
  int res = 0;
  while (b) {
    if (b & 1) res = (res + a) % mod;
    a = (a + a) % mod, b >>= 1;
  }
  return res;
}

matrix operator * (const matrix &a, const matrix &b) {
  matrix c;
  c.clear();
  for (int k = 1; k <= 2; k++)
    for (int i = 1; i <= 2; i++)
      for (int j = 1; j <= 2; j++)
        c.ma[i][j] = (c.ma[i][j] + mul(a.ma[i][k], b.ma[k][j])) % mod;
  return c;
} 

inline void power(int b) {
  while (b) {
    if (b & 1) ans = ans * base;
    base = base * base, b >>= 1;
  }
}

signed main() {
  mod = read(), a = read(), c = read();
  x0 = read(), n = read(), g = read();
  ans.clear(), base.clear();
  ans.ma[1][1] = x0, ans.ma[1][2] = c;
  base.ma[1][1] = a, base.ma[1][2] = 0, base.ma[2][1] = 1, base.ma[2][2] = 1;
  power(n);
  cout << ans.ma[1][1] % g << '\n';
  return 0;
}
posted @ 2020-09-02 21:20  Loceaner  阅读(132)  评论(0编辑  收藏  举报