题目描述
栋栋最近迷上了随机算法,而随机数是生成随机算法的基础。栋栋准备使用线性同余法(Linear Congruential Method)来生成一个随机数列,这种方法需要设置四个非负整数参数 m,a,c,X_0m,a,c,X0,按照下面的公式生成出一系列随机数 \{X_n\}{Xn}:
X_{n+1}=(aX_n +c)\bmod mXn+1=(aXn+c)modm
其中 \bmod mmodm 表示前面的数除以 mm 的余数。从这个式子可以看出,这个序列的下一个数总是由上一个数生成的。
用这种方法生成的序列具有随机序列的性质,因此这种方法被广泛地使用,包括常用的 C++ 和 Pascal 的产生随机数的库函数使用的也是这种方法。
栋栋知道这样产生的序列具有良好的随机性,不过心急的他仍然想尽快知道 X_nXn 是多少。由于栋栋需要的随机数是 0,1,\dots,g-10,1,…,g−1 之间的,他需要将 X_nXn 除以 gg 取余得到他想要的数,即 X_n \bmod gXnmodg,你只需要告诉栋栋他想要的数 X_n \bmod gXnmodg 是多少就可以了。
输入格式
一行 66 个用空格分割的整数 m,a,c,X_0,nm,a,c,X0,n 和 gg,其中 a,c,X_0a,c,X0 是非负整数,m,n,gm,n,g 是正整数。
输出格式
输出一个数,即 X_n \bmod gXnmodg。
输入输出样例
输入 #1复制
11 8 7 1 5 3
输出 #1复制
2
说明/提示
计算得 X_n=X_5=8Xn=X5=8,故(X_n \bmod g) = (8 \bmod 3) = 2(Xnmodg)=(8mod3)=2。
对于 100\%100% 的数据,n,m,a,c,X_0\leq 10^{18}n,m,a,c,X0≤1018,1\leq g\leq 10^81≤g≤108,n,m\geq 1n,m≥1,a,c,X_0\geq 0a,c,X0≥0
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 10;
ll n = 2,mod;
ll Mul(ll a, ll b, ll p)
{
if(b < 0) a = - a, b = - b;
ll res = 0;//因为是加法模拟乘法,所以res开始为0
while(b) {
if(b & 1) res = (res + a) % p;
a = (a + a) % p;
b >>= 1;
}
return res;
}
struct Mat{
ll m[MAXN][MAXN];
Mat(){
memset(m,0,sizeof(m));
}
void Build(int n){
for(int i = 1;i <= n; i++)
m[i][i] = 1;
}
};
Mat operator* (const Mat &a,const Mat &b){
Mat c;
for(int i = 1;i <= n; i++)
for(int j = 1;j <= n; j++)
for(int k = 1;k <= n; k++)
c.m[i][j] = (c.m[i][j] + Mul(b.m[i][k],a.m[k][j],mod))%mod;
return c;
}
int main()
{
ll a,c,x,m,g;
cin >> mod >> a >> c >> x >> m >> g;
Mat base,res;res.Build(n);
base.m[1][1] = a;base.m[1][2] = c;base.m[2][2] = 1;
while(m){
if(m&1) res = base * res;
base = base * base;
m >>= 1;
}
cout << (Mul(res.m[1][1],x,mod)+res.m[1][2])%mod%g;
return 0;
}