【矩阵乘法+快速乘】BZOJ2875-[NOI2012]随机数生成器

【题目大意】

已知Xn+1=(aXn+c) mod m,求Xn mod g。

【思路】

get到了longlong乘法的正确方法,快速乘。什么是快速乘呢?

简单来讲,快速幂就是模拟了二进制的竖式乘法。如:

10101 × 1011 = 10101*1+10101*2^1*1+10101*2^2*0+10101*2^3*1

代码如下:

long long multi(long long a,long long b,long long m) {
    long long ans=0;

    while(b) {
        if(b&1) (ans+=a) %= m;
        (a=a*2) %= m;
        b/=2;
    }

    return ans;
}

接下来本题的方法就是据矩阵乘法的快速幂

(a 0

c 1)自乘n次即可

注意函数里也不要忘记了开longlong..一开始我函数里面的n写成了int,WA了一发。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 ll matrix[2][2],ans_matrix[2][2];
 8 ll m,n,a,c,g,x0;
 9
10 ll ksc(ll a,ll b)
11 {
12     ll ans=0;
13     while (b)
14     {
15         if (b&1) ans=(ans+a)%m;
16         a=(a<<1)%m;
17         b>>=1;
18     }
19     return ans;
20 }
21
22 void ksm(ll n)
23 {
24     ans_matrix[0][0]=ans_matrix[1][1]=1;
25     ans_matrix[0][1]=ans_matrix[1][0]=0;
26     while (n)
27     {
28         if (n&1)
29         {
30             ans_matrix[0][0]=ksc(ans_matrix[0][0],matrix[0][0]);
31             ans_matrix[1][0]=(ksc(ans_matrix[1][0],matrix[0][0])+matrix[1][0])%m;
32         }
33         n>>=1;
34         ll tmp1=ksc(matrix[0][0],matrix[0][0]);
35         ll tmp2=(ksc(matrix[1][0],matrix[0][0])+matrix[1][0])%m;
36         matrix[0][0]=tmp1,matrix[1][0]=tmp2;
37     }
38 }
39
40 void init()
41 {
42     scanf("%lld%lld%lld%lld%lld%lld",&m,&a,&c,&x0,&n,&g);
43     matrix[0][0]=a%m,matrix[0][1]=0,matrix[1][0]=c%m,matrix[1][1]=1;
44 }
45
46 void get_ans()
47 {
48     ll ans=(ksc(ans_matrix[0][0],x0)+ans_matrix[1][0])%m;
49     ans%=g;
50     printf("%lld",ans);
51 }
52
53 int main()
54 {
55     //freopen("randoma.in","r",stdin);
56     //freopen("randoma.out","w",stdout);
57     init();
58     ksm(n);
59     get_ans();
60     return 0;
61 } 
时间: 2024-12-06 06:41:41

【矩阵乘法+快速乘】BZOJ2875-[NOI2012]随机数生成器的相关文章

bzoj2875: [Noi2012]随机数生成器

矩阵乘法. x[n] = {x[0],1} * ( {a,0} ^ n ) {b,1} 写成这样谁能看懂.... noi里的大水题.我居然 #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define LL long long using namespace std; const int maxn = 2; LL a,b,mod,g,x,n,ans; LL

矩阵(快速幂):COGS 963. [NOI2012] 随机数生成器

963. [NOI2012] 随机数生成器 ★★   输入文件:randoma.in   输出文件:randoma.out   简单对比 时间限制:1 s   内存限制:128 MB [问题描述] 栋栋最近迷上了随机算法,而随机数是生成随机算法的基础.栋栋准备使用线性同余法(Linear Congruential Method)来生成一个随机数列,这种方法需要设置四个非负整数参数m,a,c,X[0],按照下面的公式生成出一系列随机数{Xn}:X[n+1]=(aX[n]+c) mod m 其中mo

BZOJ 2875: [Noi2012]随机数生成器( 矩阵快速幂 )

矩阵快速幂...+快速乘就OK了 -------------------------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; typedef long long ll; ll MOD, a, c, x, n, g; ll MUL(ll a, ll b) { ll ans = 0; for(; b; b >>= 1

【NOI2012】【BZOJ2875】随机数生成器

BZOJ题面不正常我贴一下别的OJ题面把 [问题描述] 栋栋最近迷上了随机算法,而随机数是生成随机算法的基础.栋栋准备使用线性同余法(Linear Congruential Method)来生成一个随机数列,这种方法需要设置四个非负整数参数m,a,c,X[0],按照下面的公式生成出一系列随机数{Xn}: X[n+1]=(aX[n]+c) mod m 其中mod m表示前面的数除以m的余数.从这个式子可以看出,这个序列的下一个数总是由上一个数生成的. 用这种方法生成的序列具有随机序列的性质,因此这

2875: [Noi2012]随机数生成器 - BZOJ

DescriptionInput 包含6个用空格分割的m,a,c,X0,n和g,其中a,c,X0是非负整数,m,n,g是正整数. Output 输出一个数,即Xn mod gSample Input 11 8 7 1 5 3 Sample Output2 快速幂+快速乘 1 type 2 matrix=array[1..2,1..2]of int64; 3 var 4 a,c,p,x0,n,g:int64; 5 x,y:matrix; 6 7 function kc(x,y:int64):int

快速求斐波那契数列(矩阵乘法+快速幂)

斐波那契数列 给你一个n:f(n)=f(n-1)+f(n-2) 请求出 f(f(n)),由于结果很大请 对答案 mod 10^9+7; 1<=n<=10^100; 用矩阵乘法+快速幂求斐波那契数列是经典应用: 矩阵公式 C i j=C i k *C k j; 根据递推式 构造2*2矩阵: 原始矩阵 1 0 0 1 矩阵 2 1 1 1 0 原始矩阵与矩阵 2相乘达到转化状态效果: 对矩阵二进行快速幂 乘法:达到快速转化矩阵的效果: 即使达到快速转化状态:那么大的数据范围也很难求解: 高精?这有

[NOI2012] 随机数生成器

963. [NOI2012] 随机数生成器 ★★   输入文件:randoma.in   输出文件:randoma.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 栋栋最近迷上了随机算法,而随机数是生成随机算法的基础.栋栋准备使用线性同余法(Linear Congruential Method)来生成一个随机数列,这种方法需要设置四个非负整数参数m,a,c,X[0],按照下面的公式生成出一系列随机数&{X_n}&: Xn+1=(aXn+c)mod m 其中m

bzoj 2875 [Noi2012]随机数生成器 矩阵乘法

题面 题目传送门 解法 矩阵乘法sb题 注意整数乘法要使用龟速乘,否则会爆long long 代码 #include <bits/stdc++.h> #define int long long using namespace std; struct Matrix { int a[4][4]; void Clear() {memset(a, 0, sizeof(a));} }; int n, m, a, c, x, g; int mul(int x, int y) { int ret = 0;

codevs1281 矩阵乘法 快速幂 !!!手写乘法取模!!! 练习struct的构造函数和成员函数

对于这道题目以及我的快速幂以及我的一节半晚自习我表示无力吐槽,, 首先矩阵乘法和快速幂没必要太多说吧,,嗯没必要,,我相信没必要,,实在做不出来写两个矩阵手推一下也就能理解矩阵的顺序了,要格外注意一些细节,比如快速幂时ans矩阵的初始化方式,快速幂的次数,矩阵乘法过程中对临时矩阵的清零,最后输出结果时的初始矩阵...矩阵快速幂好理解但是细节还是有点小坑的.. 下面就是满满的槽点,,高能慎入!!! 对于这个题目要求矩阵过程中对m取模,结果对g取模,我表示难以接受,,上来没看清题直接wa19个点,另