bzoj2875 [Noi2012]随机数生成器

Description

栋栋最近迷上了随机算法,而随机数生成 是随机算法的基础。栋栋准备使用线性同余法(Linear Congruential Method)来生成一个随机数列,这种方法需要设置四个非负整数参数m, a, c, X0,按照下面的公式生成出一系列随机数<Xn>: 
Xn+1  =  (aXn  +  c) mod m ,mod m 表示前面的数除以m的余数。从这个式子可以看出,这个序列的下一个数总是由上一个数生成的。 
用这种方法生成的序列具有随机序列的性质,因此这种方法被广泛地使用,包括常用的C++和Pascal 的产生随机数的库函数使用的也是这种方法。 
栋栋知道这样产生的序列具有良好的随机性,不过心急的他仍然想尽快知道Xn 是多少。由于栋栋需要的随机数是0, 1,…, g − 1 之间的,他需要将Xn除以g。取余得到他想要的数,即Xn mod g,你只需要告诉栋栋他想要的数Xn mod g 是多少就可以了。

Input

包含6个用空格分割的m,a,c,X0,n和g,其中a,c,X0是非负整数,m,n,g是正整数。

Output

输出一个数,即Xn mod g

Sample Input

11 8 7 1 5 3

Sample Output

2

HINT

1<=n,m,a,c,X0<=10^18,1<=g<=10^8

 

正解:递推+矩阵快速幂。

矩阵快速幂水题。我用龟速乘居然T了,改成防爆乘轻松AC。。

初始矩阵:

x0 c

0 0

转移矩阵:

a 0

1 1

然后快速幂搞搞就行了。。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <complex>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define il inline
16 #define RG register
17 #define ll long long
18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
19 
20 using namespace std;
21 
22 struct data{ ll a[3][3]; }ans,b;
23 
24 ll m,a,c,x,n,g;
25 
26 il ll mul(RG ll a,RG ll b){
27     RG ll res=a*b-(ll)((long double)(a)*b/m+0.5)*m;
28     if (res<0) res+=m; return res;
29 }
30 
31 il data matrix(RG data a,RG data b){
32     RG data ans; memset(ans.a,0,sizeof(ans.a));
33     for (RG ll i=1;i<=2;++i)
34     for (RG ll j=1;j<=2;++j)
35         for (RG ll k=1;k<=2;++k){
36         ans.a[i][j]+=mul(a.a[i][k],b.a[k][j]);
37         if (ans.a[i][j]>=m) ans.a[i][j]-=m;
38         }
39     return ans;
40 }
41 
42 il data qpow(RG data a,RG ll b){
43     RG data ans=a; b--;
44     while (b){
45     if (b&1) ans=matrix(ans,a);
46     a=matrix(a,a),b>>=1;
47     }
48     return ans;
49 }
50 
51 il void work(){
52     cin>>m>>a>>c>>x>>n>>g;
53     b.a[1][1]=a,b.a[2][1]=b.a[2][2]=1,b=qpow(b,n);
54     ans.a[1][1]=x,ans.a[1][2]=c,ans=matrix(ans,b);
55     printf("%lld\n",ans.a[1][1]%g); return;
56 }
57 
58 int main(){
59     File("rand");
60     work();
61     return 0;
62 }

 

posted @ 2017-03-14 19:44  wfj_2048  阅读(76)  评论(0编辑  收藏