逆元知識普及(進階篇) ——from Judge

關於一些逆元知識的拓展

剛艹完一道 提升- 的黃題(曹衝養豬) ,因而又來混一波講解了html

  ——承接上文掃盲篇npm

 


 

4、Lucas定理(求大組合數取模)

 

題外話

這裏Lucas定理的證實須要用到不少關於組合數的定理知識, 函數

那麼關於一些組合數的知識,詳情你能夠看這裏:Binamoto' blogui

 

 

再講講lucas定理這個東西(擴展lucas就不講了,由於不大會…咳咳,而後也不怎麼會用到吧)spa

基本公式: C(n,m) ≡ C(n/p,m/p)*C(n%p,m%p) (mod p)

(也就是: C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p )

適用範圍:n 和 m 很是大,而模數 p 比較小的狀況 (偷懶)

Lucas 定理的運用

將組合數中的 n 和 m 不斷除以 p , 同時用除 p 的餘數作組合數,累計入答案。 即,不斷調用基本公式,遞歸求解,直至 m 等於 0 . 用上述例子就是:令C(n/p,m/p) ≡ C( (n/p)/p,(m/p)/p ) * C( (n/p)%p,(m/p)%p ) (mod p) 而後把 C(n/p,m/p) 求得的解 帶入基本公式, 求出 C(n,m)%p 的值

證實及推導:

如下證實推導源自 Lucas定理——推導及證實.net

要證:C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p 即證:C(n,m)=C(n/p,m/p)*C(n%p,m%p) 證實條件:已知p是素數,n、m、p爲整數。

1.由二項式定理得: 
0 ,且 1
code


2.由費馬小定理得:
(1)式 :$(x + 1) ^p ≡ x+1 (mod~ p)$ **[ 由x ^p ≡ x (mod p) , x 用 (x+1) 代替獲得]**
(2)式 :$x ^p + 1 ≡ x+1 (mod~ p)$ **[ 由x ^p ≡ x (mod p) , 等式兩邊同時+1獲得]**htm

合併 1 、2 兩式,獲得:
(3)式 :$(x + 1) ^p ≡ x ^p + 1 (mod~ p)$blog

3.由 $n = n/p *p + n\%p$ . 則:遞歸

$(x+1) ^p ≡ (x+1) ^{n/p *p} * (x+1)^{n\%p} (mod p)$
帶入三式: $(x+1)^p ≡ (x^p +1)^{n/p}*(x+1)^{n\%p} (mod p)$

將上式由二項式公式可轉化爲:

$$\sum_{z=0}^n C_n^z ·x^z ≡ \sum_{i=0}^{n/p} C_{n/p}^i ~·~x^{p ~·~i} \sum_{j=0}^{n\%p} C_{n\%p}^j ·x^j \Big(mod ~~p \Big)$$

任意一個Z,必存在一個 i , j 知足:x ^ z = x ^ (p* i) * x^ j (即知足:n = n/p *p + n%p), 
當且僅當: i=z/p,j=z%p 時成立 
此時, C(n,m)=C(n/p,m/p)*C(n%p,m%p) 成立 
證畢

相信這些東西你在看完後任然是懵逼的(me too)

那麼你能夠看看另一個證實(來自可愛的 Binamoto ):

設 $n=s*p+q,m=t*p+r(q,r<=p)$
咱們要證 $C_{t*p+r}^{s*p+q} ≡C_{t}^{s} * C_{r}^{q} (modp)$
首先得有個前置知識,費馬小定理 $x^p ≡ x (mod p)$
那麼 $(x+1)^p ≡ x+1(mod p)$
且 $x^p+1 ≡ x+1 (mod p)$
因此 $(x+1)^p ≡ x^p+1 (mod p)$
而後 $(x+1)^n≡(x+1)^{s*p+q}$
$ ≡ ((x+1)^p)^{s} * (x+1)^q$
$ ≡ (x^p+1)^s * (x+1)^q ≡ (x^p+1)^s * (x+1)^q$
而後用二項式定理展開
≡$\sum_{i=0}^{s}C_{s}^{i}*x^{i*p} * \sum_{j=0}^{1}C_{q}^{j}*x^{j}$
總之就是 $(x+1)^p ≡ \sum_{i=0}^{s} C_{s}^{i} * x^{i*p} *\sum_{j=0}^{q} C_{q}^{j}*x^j$
而後考慮把兩邊的多項式展開一下
那麼兩邊確定都有 $x^{m}$ 即 $x^{t*p+r}$ 這一項(這是最上面的假設)
左邊的 $x^m$ 的係數,根據上面的性質4推出來,應該是 $C_{n}^{m}$
而後右邊嘞?只有 $i=t$ , $j=r$ 的時候纔會有這一項,因此這一項的係數就是 $C_s^t * C_q^r$
而後又由於 $s=n/p$,$t=n%p$,$q=m/p$,$r=m%p$
而後就能證實: $$C(n,m) ≡ C(n/p,m/p) * C{n%p,m%p} (mod p)$$
然而萬一 $q<r$ 該怎麼辦?那樣的話 $j$ 根本不可能等於 $r$ 啊?

因此那樣的話答案就是 $0$
由於上面乘上 $C{n%p,m%p}$ 答案就是 $0$
如何證實?

咱們設 $f=n-m=z*q+x$
由於 $r>t$ , $x+r ≡ t (mod p)$
因此 $x+r=p+t$
又由於 $z*p+x+q*p+r = s*p+t$
因此 $z+q=s-1$
那麼帶進通項公式 $C_{n}^{m}= \dfrac{n!}{m! * f!}$ 以後,分子中有 $s$ 個 $p$ ,分母中有 $s-1$ 個 {p} ,
抵消以後分子中還有一個 $p$ ,那麼這個數就是 $p$ 的倍數, $p$ 必然餘 $0$.

 

Lucas 的代碼(同上隨意手打):

//by Judge
define ll long long ll mod; inline ll quick_pow(ll x,ll p){ ll ans=1; while(p){ if(p&1) ans=ans*x%p; x=x*x%p, b>>=1; } return ans; } inline ll C(ll n,ll m){ ll cn=1,cm=1,res=1; if(n<m) return 0; if(n==m) return 1; if(m>n-m) m=n-m; for(ll i=0;i<m;++i){ cn=(cn*(n-i))%mod; cm=(cm*(m-i))%mod; } res=(cn*quick_pow(cm,mod-2))%mod;   //除法轉換求逆元
    return res; } ll Lucas(ll n,ll m){ ll ans=1; while(n && m && ans){ ans=(ans*C(n%mod,m%mod))%mod;   //拆分+遞歸
        n/=mod, m/=mod; } return ans; }

 

 關於 Ex Lucas

這玩意兒別學了,要先會 CRT (多是 exCRT?)的。

 


 

5、解線性同餘方程組

其實這個玩意兒沒什麼高大上的,就CRT ... 什麼的,你是沒看過 NOI  day2 T1  吧,那個玩意兒...不說了,勾起了一些不美好的回憶(聽說該題是全部題裏面最簡單的)

emmmm,首先解釋一下這個東西。

線性同餘方程組:

  ( 求解 X ,其中 X  知足如下條件 )

  X≡b1 (mod a1)

  X≡b2 (mod a2)

  ...

  X≡bn (mod an)

 對,就和上面同樣,是 n  個式子,(通常)讓你求出 X  的最小正整數解(即知足 n 個式子的限制條件),這裏看不大懂的話你能夠看看曹衝養豬這道題,那個比喻也是蠻生動的

那麼這玩意兒怎麼解呢? 別急,咱們得先來看看 X  有解的條件。

其實條件很簡單: b2 - b1  ≡  0 ( mod gcd(a1,a2) )

證實及推導:

  設  X = a1 * x + b1 , 則 a1 * x + b1 ≡ b2 (mod a2)   (就是在式 2 中把 X 替換掉)

  => a1 * x ≡ b2 - b1 (mod a2) => a1 * x + a2 * y = b2 - b1  

  那麼和逆元有解條件的證實相似,只有  (b2-b1) | gcd(a1,a2)  時,原式有解(其中  (a) | (b)  表明 a 能被 b 整除 )

  證畢

 

因此呢?證實完了以後有什麼用處麼? 固然有。

你看啊,上面的那個式子咱們推着推着就退出來了一個方程對吧?是否是有點眼熟? (提示一下 ax + by  )

emmmm 對吧。就是相似一個擴歐的式子啊,由於 a1 和 a2 已知了啊。

而後咱們用擴歐求出 a1*x + a2*y = gcd(a1,a2)   中 y1 的解就離勝利不遠了

而後你看看咱們解出來的這個 x 和 y  ,其實它並非 a1 * x + a2 * y = b2 - b1   的解(這不顯然嘛)

可是! b2 - b1  是能夠整除 gcd(a1,a2)  的(不然就是無解的狀況),因此咱們只須要讓  x 和  y   乘以 (b2-b1)/gcd(a1,a2)  就能夠令等式成立了

而後咱們把 x  帶入 X = a1 * x + b1  不就能夠獲得答案了?

同餘方程的合併:

可是這裏有個關鍵問題對吧(上面的這些推導只求出了 兩個式子的解啊,咱們不是要求知足n  個式子的解嗎?)

因此咱們要考慮的就是把這個方法延續下去...也就是說咱們要把 一、2  兩個式子合併起來,與第  3   個式子繼續進行以上操做。

怎麼合併? =>   X=X' (mod lcm(a1,a2))   (其中 X'  是由前兩個式子獲得的答案,這裏咱們就是讓 bi = X' ,  ai = lcm(a1,a2) )

爲何能夠這樣合併? 你只要知道 X'  是原式在 lcm(a1,a2)   範圍內惟一的解就行了

(你們感性理解一下就好,我也不知道怎麼證,已經頹廢到懶得想了)

咳咳...簡單解釋一下:

 

  你應該是知道在  a1 * x + a2 * y = b2 - b1   這個等式中的 x 和 y  的解釋不止一種的(這個不知道我也沒辦法)

  咱們要改變着個解 就是 讓 x  加上(減去) a2/d ,而後讓 y 減去(加上) a1/d  ,等式依舊成立。(這裏 d 表示 gcd(a1,a2) ,下同 )

  也就是說咱們要用到的  x  能夠加上或減去任意個 a2/d ,而後你看一下 :  X = a1 * x + b1  ,

  也就是說咱們每次讓  x  變化  ± a2  以後,X  的值就會加上或減去  a1 * a2/d  (即 X 能夠加上任意個 lcm(a1,a2) ),

  由此咱們能夠很容易看出:  X   在 lcm(a1 , a2)   範圍內的解是惟一的。

 

因此兩個式子就能夠那樣合併了...

還看不懂?woc 以前都白推了?emmm ,好吧,讓咱們看看以前的結論(過程結論):

  咱們可讓  X   的值加上任意個  lcm(a1,a2)  

什麼意思? mod lcm(a1,a2)  = X  的意思啊!就是說任意一個數只要能 mod lcm(a1,a2)  =  X

因此這不就和以前那一堆式子 : X ≡  bi  (mod ai)   同樣了? 推導完畢!

......

那麼以後咱們就反覆迭代以上步驟,獲得最終的答案

而後呢...沒而後了啊,而後就是代碼部分了啊QAQ

 

代碼:

int ex_gcd(int a,int b,int& x,int& y){  //原本不想附 ex_gcd 代碼來着的...
    if(!b) { x=1,y=0;return a; } int d=ex_gcd(b,a%b,y,x); y-=a/b*x; return d; } inline ll solv(int n){ ll x=0,m=1; // x 記錄前兩個方程組的答案,初始爲 0, m 記錄前面全部的 a 的 lcm for(int i=1;i<=n;++i){ scanf("%lld%lld",&A,&B); ll b=B-x,d=ex_gcd(m,A,z,y); if (b%d!=0) return -1ll; ll t=b/d*z%(A/d); x+=m*t,m*=A/d; } return x>0?x:x+m; }

 

關於exCRT

 這東西別學了,煩的要命...

 


 

6、BSGS 定理 baby-step giant-step

BSGS的用處:

BSGS,魔鬼的步伐,怎麼說呢...

有關BSGS的題目大多就是讓你求 知足 $a^n ≡ 1 (mod\ p)$ 的最小的 n ,p 爲質數

注意 p 爲質數!不然就是 exBSGS

注意 n 是最小的,而後咱們求出的 n 就是 a 模 p 意義下的階

 

題外話:

這個東西很重要,爲何?由於 NTT 裏面有用到原根...

原根是什麼東西?原根就是:

對於一個數 a ,若其知足 a 在模 p 意義下的階等於 p 的 φ 值(就是歐拉函數值),則 a 爲 p 的階

那麼當 p 爲質數時, φ 就爲 p-1 咯。

小插曲:你知道大質數 998244353 怎麼來的麼?(不要告訴我你不知道這個模數)

其實它是從 NTT 中出來的,由於它的一個原根是 3 ,比較好記

另外,$998244353=7 * 17 * 2^23 + 1$

 

 

BSGS是什麼:

講了這麼多沒用的。。。咱們回到原來的問題

 

本來的問題是: 讓你求 知足 $a^n ≡ 1 (mod\ p)$ 的最小的 n

 

那麼咱們考慮分塊,咱們令  $a^n=a^{gt} \times a^h (mod\ p)$

其中 $t = \sqrt{p}$, g 、h 是未知數

 

那麼 h 確定是小於 t 的對吧?否則的話只要讓 g 加上一,h就能夠減去 t, 而後等式仍然成立

那麼咱們先考慮 g 的最大值是多少:

咱們看看,a^p-1 是多少? 明顯是 1 吧? 根據費馬小定理來的,不證了

那麼也就是說 p-1 是一個 a 的循環節,那麼 g 的最大值就是 $\sqrt{p}$ 了

 

而後考慮一下咱們只須要$O(\sqrt{p})$去枚舉 g ,而後算出值存進map(或者hash表,更快)

而後原問題就能夠轉換爲求找出是否存在 h ($h<=\sqrt{p}$) 使得 $a^{gt} \times a^h ≡ 1(mod\ p)$

而後移一下項就能夠變成 $a^{gt}  a^{-h}(mod\ p)$   ,其中 $a^{-h}$就是 $a^h$ 的逆元

而後再$O(\sqrt{p})$枚舉 h ,算出 $a^{-h}(mod\ p)$ 而後看看 map 中有沒有這個數,有的話 g*t+h 就是原等式的一個解了

其實不難吧?分塊暴力嘛

(poj)

1 inline void insert(int x,int y){ int k=x%mod;
2     hs[++pat]=x,id[pat]=y,nxt[pat]=head[k],head[k]=pat;
3 }
4 inline int find(int x){  int k=x%mod;
5     for(int i=head[k];i>=0;i=nxt[i])
6         if(hs[i]==x) return id[i]; return -1;
7 }
8 inline int BSGS(int a,int b,int n){
9     memset(head,-1,sizeof(head));
10     pat=0; if(b==1) return 0;
11     int m=sqrt(n+0.0),j; ll x=1,p=1;
12     for(int i=0;i<m;++i,p=p*a%n)
13         insert((p*b%n),i);
14     for(ll i=m;i<=n;i+=m)
15         if((j=find(x=x*p%n))!=-1) return i-j;
16     return -1;
17 }

 

 

好了,Judge's Class  終於水完了,繼續刷水題去   Bye~

相關文章
相關標籤/搜索