棟棟最近迷上了隨機演算法,而隨機數是生成隨機演算法的基礎。棟棟準備使用線性同餘法(linear congruential method)來生成乙個隨機數列,這種方法需要設定四個非負整數引數 \(m,a,c,x_0\),按照下面的公式生成出一系列隨機數 \(\\):
\[x_=(ax_n +c)\bmod m
\]其中\(mod\ m\) 表示前面的數除以 \(m\) 的餘數。從這個式子可以看出,這個序列的下乙個數總是由上乙個數生成的。
棟棟知道這樣產生的序列具有良好的隨機性,不過心急的他仍然想盡快知道 \(x_n\) 是多少。由於棟棟需要的隨機數是 \(0,1,\dots,g-1\) 之間的,他需要將 \(x_n\) 除以 \(g\) 取餘得到他想要的數,即 \(x_n \bmod g\),你只需要告訴棟棟他想要的數 \(x_n \bmod g\) 是多少就可以了。
一行 \(6\) 個用空格分割的整數 \(m,a,c,x_0,n\) 和 \(g\),其中 \(a,c,x_0\) 是非負整數,\(m,n,g\) 是正整數。
輸出乙個數,即 \(x_n \bmod g\)。
輸入
11 8 7 1 5 3輸出計算得 \(x_n=x_5=8\),故\((x_n \bmod g) = (8 \bmod 3) = 2\)。
對於 \(100\%\) 的資料,\(n,m,a,c,x_0\leq 10^\),\(1\leq g\leq 10^8\),\(n,m\geq 1\),\(a,c,x_0\geq 0\)。
給出了乙個迷惑式子,讓你算出來式子的第\(n\)項,然後\(mod\ g\)的結果
看到這樣乙個個的遞推式子,乙個個用\(for\)迴圈來推肯定不行,所以很容易就會想到要用到矩陣快速冪來求。那麼我們現在的主要任務就是構造矩陣來進行乘法運算。
首先看到題目中給出的式子:
\[x_=(ax_n+c)\ mod\ m
\]取模運算可以暫且先不看,因為對結果沒什麼影響,在矩陣乘法的時候進行取模就行了。所以轉化成如下式子:
\[x_=ax_n+c
\]那麼我們就可以根據這個式子來構造矩陣。由矩陣的乘法運算為結果矩陣的\(i\)行\(j\)列為前邊矩陣乙個的第\(i\)行乘以另乙個的第\(j\)列,所以我們可以得出如下的矩陣遞推式子:
\[\left[
\begin
x_\\
c \end
\right]\times \left[
\begin
a & 1\\
0 & 1
\end
\right] = \left[
\begin
x_\\
c \end
\right]
\]這裡用\(x_\)這一列分別乘以右邊矩陣的第一第二行,得到結果的矩陣,那麼我們就可以根據這個遞推式子來進行矩陣快速冪。
這裡乘法的運算過程如下:
\[x_\times a+c\times 1 = x_n
\]\[x_\times 0+c\times 1 = c
\]由此得到結果矩陣
這裡的矩陣做乘法的時候需要用到龜速乘,不然會爆\(long\ long\)
#includeusing namespace std;
#define int long long
struct node;
int m,a,c,x0,g,n;
int ksj(int a,int b)
return ans;
}node mul(node a,node b,int c)
}} return ans;
}node ans;
void qpow(node &ans,node b,int c)
}signed main()
noi2012隨機數生成器
x n 1 ax n c mod m其中mod m表示前面的數除以m的餘數。從這個式子可以看出,這個序列的下乙個數總是由上乙個數生成的。用這種方法生成的序列具有隨機序列的性質,因此這種方法被廣泛地使用,包括常用的c 和pascal的產生隨機數的庫函式使用的也是這種方法。棟棟知道這樣產生的序列具有良好...
NOI2012 隨機數生成器
bzoj2875 第一眼看是矩陣乘法 高精,順便藉此機會學了一下壓八位高精 然後一直wa 拍到最後拍不下去了,索性重打了一遍,不過沒用高精,用的類似快速冪的快速乘,同樣解決了溢位問題 快速乘 矩陣乘法 include include include include typedef long long...
NOI2012 隨機數生成器 矩陣乘法
棟棟最近迷上了隨機演算法,而隨機數是生成隨機演算法的基礎。棟棟準備使用線性同餘法 linear congruential method 來生成乙個隨機數列,這種方法需要設定四個非負整數引數m,a,c,x 0 按照下面的公式生成出一系列隨機數 x n 1 ax n c mod m用這種方法生成的序列具...