洛谷 P2044 [NOI2012] 随机数生成器
题意
给定 \(m , a , c X_0 , n , g\) ,且满足 \(X_{n+1} = (a X_n + c) \quad mod \quad m\) , 求 \(X_n \quad mod \quad g\)
思路
矩阵快速幂加速递推方程的板子题
但是\(long \quad long\) 乘法会溢出 , 需要解决
两种办法 :
- 防溢出乘法
原理和快速幂差不多QAQ
- __int128
这个输出需要用快写
代码
防溢出乘法
#include<bits/stdc++.h>
using namespace std;
#define int long long int
inline int read() {
int ans = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')f = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
ans = ans * 10 + ch - '0';
ch = getchar();
}
return ans * f;
}
int m,a,c,X0,n,g;
int mt[4][4],tmp[4][4],ans[4][4];
int cf(int a,int b) {
int ans = 0;
while (b) {
if (b&1)
ans = ( ans + a) % m;
a = (a + a) %m;
b>>=1;
}
return ans;
}
void mul() {
for (int i = 1; i<=3; i++)
for (int j =1; j<=3; j++) {
for (int k = 1; k<=3 ;k++)
tmp[i][j] = (tmp[i][j] + cf(mt[i][k], ans[k][j]))%m;
}
for (int i = 1; i<=3; i++)
for (int j =1;j<=3;j++)
ans[i][j] = tmp[i][j], tmp[i][j] = 0;
}
void selfmul() {
for (int i = 1; i<=3; i++)
for (int j =1; j<=3; j++) {
for (int k = 1; k<=3 ;k++)
tmp[i][j] = (tmp[i][j] +cf( mt[i][k] , mt[k][j]))%m;
}
for (int i = 1; i<=3; i++)
for (int j =1;j<=3;j++)
mt[i][j] = tmp[i][j], tmp[i][j] = 0;
}
void qmpow(int k) {
while (k) {
if (k&1) mul();
selfmul();
k >>=1;
}
}
signed main() {
m = read(),a=read(),c=read(),X0=read(),n=read(),g=read();
mt[1][1] = a,mt[1][3] = c,mt[2][1] = 1,mt[3][3] = 1;
for (int i = 1; i<=3;i++)ans[i][i] = 1;
int x1 = (cf(a , X0) + c) % m;
qmpow(n);
cout<<(cf(ans[2][1] ,x1) + cf(ans[2][2], X0) + ans[2][3])%m % g;
return 0;
}
__int128
#include<bits/stdc++.h>
using namespace std;
#define int __int128
inline int read() {
int ans = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')f = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
ans = ans * 10 + ch - '0';
ch = getchar();
}
return ans * f;
}
int m,a,c,X0,n,g;
int mt[4][4],tmp[4][4],ans[4][4];
void mul() {
for (int i = 1; i<=3; i++)
for (int j =1; j<=3; j++) {
for (int k = 1; k<=3 ;k++)
tmp[i][j] = (tmp[i][j] + mt[i][k] * ans[k][j])%m;
}
for (int i = 1; i<=3; i++)
for (int j =1;j<=3;j++)
ans[i][j] = tmp[i][j], tmp[i][j] = 0;
}
void selfmul() {
for (int i = 1; i<=3; i++)
for (int j =1; j<=3; j++) {
for (int k = 1; k<=3 ;k++)
tmp[i][j] = (tmp[i][j] + mt[i][k] * mt[k][j])%m;
}
for (int i = 1; i<=3; i++)
for (int j =1;j<=3;j++)
mt[i][j] = tmp[i][j], tmp[i][j] = 0;
}
void qmpow(int k) {
while (k) {
if (k&1) mul();
selfmul();
k >>=1;
}
}
void print(int a) {
if (a==0){putchar('0'); return ;}
if (a<0){putchar('-'),a=-a;}
static int sta[50];
int top = 0;
while (a) {
sta[++top] = a % 10;
a/=10;
}
while (top)
putchar(sta[top--] + '0');
}
signed main() {
m = read(),a=read(),c=read(),X0=read(),n=read(),g=read();
mt[1][1] = a,mt[1][3] = c,mt[2][1] = 1,mt[3][3] = 1;
for (int i = 1; i<=3;i++)ans[i][i] = 1;
int x1 = (a * X0 + c) % m;
qmpow(n);
print((ans[2][1] *x1 + ans[2][2] * X0 + ans[2][3])%m % g);
return 0;
}

浙公网安备 33010602011771号