【学习笔记】原根 / BSGS / 扩展BSGS证明及模板
文章目錄
- 原根
- BSGS大步小步算法
- 擴展BSGS
原根
如果兩個整數a,ba,ba,b互質,則有a?(b)%b=1a^{\phi(b)}\%b=1a?(b)%b=1
定義模bbb意義下的aaa的階為使ad%b=1a^d\%b=1ad%b=1的最小正整數ddd
顯然,模bbb的階d∣?(b)d|\phi(b)d∣?(b)
如果模bbb意義下aaa的階為?(b)\phi(b)?(b),則稱aaa為bbb的原根
歐拉證明了(我證明不了)
模bbb存在原根的充要條件為:b=2,4,pn,2pnb=2,4,p^n,2p^nb=2,4,pn,2pn,其中ppp為奇素數,n∈N?n∈N^*n∈N?
當模bbb有原根時,其原根個數為?(?(b))\phi(\phi(b))?(?(b))
那么如何求一個數的原根?
首先判斷它是否有原根
如果有,一般最小原根都很小,可以選擇美麗的暴力
預處理出?(b)\phi(b)?(b)的所有因子,存放在數組DDD中
在[2,?(b))[2,\phi(b))[2,?(b))區間中,從小到大米枚舉變量iii
如果存在j∈Dj∈Dj∈D,使得i?(b)j%b=1i^{\frac{\phi(b)}{j}}\%b=1ij?(b)?%b=1,則iii不是原根,否則iii是原根
為什么這樣是正確的呢?
因為如果存在一個數1≤x<?(b)1\le x<\phi(b)1≤x<?(b),使得ix%b=1i^x\%b=1ix%b=1
則x∣?(b)x|\phi(b)x∣?(b),并且一定存在一個?(b)\phi(b)?(b)的質因子jjj,使得x∣?(b)jx|\frac{\phi(b)}{j}x∣j?(b)?
BSGS大步小步算法
BSGS是用來解決離散對數問題的
即ax≡b(modp)a^x\equiv b\ (mod\ \ p)ax≡b?(mod??p),其中a,b,pa,b,pa,b,p已知,且(a,p)=1(a,p)=1(a,p)=1,求xxx
因為a?(p)≡1(modp),?(p)<pa^{\phi(p)}\equiv 1\ (mod\ \ p),\phi(p)<pa?(p)≡1?(mod??p),?(p)<p
所以可以采取枚舉法,在O(p)O(p)O(p)的時間復雜度求出xxx
而BSGSBSGSBSGS可以在O(p)O(\sqrt{p})O(p?)的時間復雜度內求出xxx
令m=?p?,r=xmodmm=\lceil \sqrt{p} \rceil,r=x\mod mm=?p??,r=xmodm,則x=k?m+rx=k*m+rx=k?m+r,其中0≤k<m,0≤r<k0\le k<m,0\le r<k0≤k<m,0≤r<k,有
ak?m+r≡b(modp)a^{k*m+r}\equiv b\ \ (mod\ \ p)ak?m+r≡b??(mod??p)
因為(a,p)=1(a,p)=1(a,p)=1,方程兩邊同乘a?ra^{-r}a?r
ak?m≡b?a?r(modp)a^{k*m}\equiv b*a^{-r}\ \ (mod\ \ p)ak?m≡b?a?r??(mod??p)
對于0≤i<r0\le i<r0≤i<r,求出所有的b?a?1modpb*a^{-1}\mod\ \ pb?a?1mod??p,將其值以及iii存入mapmapmap
然后再求左邊的aj?mmodp,(0≤j<k)a^{j*m}\mod p,(0\le j<k)aj?mmodp,(0≤j<k),并在mapmapmap里尋找是否出現過相同的值
如果有,代表著同余,已經找到了答案,如果沒有則是無解
然而。。。
可以稍微轉變一下算法過程,避免求逆元的操作
x=k?m+r=(k+1)?m?m+r=(k+1)?m?(m?r)x=k*m+r=(k+1)*m-m+r=(k+1)*m-(m-r)x=k?m+r=(k+1)?m?m+r=(k+1)?m?(m?r)
因為有 r<mr<mr<m 所以考慮換一種方式枚舉 r←m?rr\leftarrow m-rr←m?r
?x=k?m?r,(1≤k≤m,0≤r<m)\Rightarrow x=k*m-r,(1\le k\le m,0\le r<m)?x=k?m?r,(1≤k≤m,0≤r<m)
則ak?m?r≡b(modp)a^{k*m-r}\equiv b\ \ (\mod p)ak?m?r≡b??(modp)
兩邊同時乘以ara^rar
ak?m≡b?ar(modp)a^{k*m}\equiv b*a^r\ \ (\mod p)ak?m≡b?ar??(modp)
先求出右邊所有的b?ai(modp)(1≤i≤m)b*a^i(\mod p)(1\le i\le m)b?ai(modp)(1≤i≤m)保存在mapmapmap中
然后再求左邊的aj?mmodpa^{j*m}\mod\ paj?mmod?p,并在mapmapmap中查找是否出現過
如果出現過,左邊枚舉的是jjj,右邊枚舉的是iii,則答案為x=j?m?ix=j*m-ix=j?m?i,這樣就避免了求逆元的操作,卻仍然用到了逆元
因為推導必須是等價推導,只有當(a,p)=1(a,p)=1(a,p)=1,即ara^rar逆元存在時,才可以大膽兩邊同乘ara^rar等價,因為如果(a,p)≠1(a,p)≠1(a,p)?=1,式子倒推不回去
#include <map> #include <cmath> #include <cstdio> using namespace std; #define int long long map < int, int > mp; int a, mod, r;int bsgs() {mp.clear();int m = ceil( sqrt( mod ) );int tmp = 1;for( int i = 1;i <= m;i ++ ) {tmp = tmp * a % mod;mp[tmp * r % mod] = i;}int res = 1;for( int i = 1;i <= m;i ++ ) {res = res * tmp % mod;if( mp[res] ) return m * i - mp[res];}return -1; }signed main() {int ans;while( ~ scanf( "%lld %lld %lld", &mod, &a, &r ) ) {r %= mod, a %= mod;if( r == 1 ) ans = 0;else if( ! a ) {if( r ) ans = -1;else ans = 1;}else ans = bsgs();if( ans == -1 ) printf( "no solution\n" );else printf( "%lld\n", ans );}return 0; }擴展BSGS
對于ax≡b(modp)a^x\equiv b(\mod p)ax≡b(modp)
如果(a,p)>1(a,p)>1(a,p)>1,則無法直接套用BSGS,此時就要用到擴展BSGS
將要求解的式子變形
ax+k?p=ba^x+k*p=bax+k?p=b
設(a,p)=g(a,p)=g(a,p)=g,若bbb不是ggg的倍數,則方程無解
不過有一個例外b=1,x=0b=1,x=0b=1,x=0,這個情況特判即可
式子左右兩邊除以ggg
ax?1ag+kpg=bga^{x-1}\frac{a}{g}+k\frac{p}{g}=\frac{b}{g}ax?1ga?+kgp?=gb?
令a′=ag,p′=pg,b′=bga'=\frac{a}{g},p'=\frac{p}{g},b'=\frac{b}{g}a′=ga?,p′=gp?,b′=gb?
ax?1a′+kp′=b′a^{x-1}a'+kp'=b'ax?1a′+kp′=b′
若a,p′a,p'a,p′仍然不互質,則繼續以上操作找出a,p′a,p'a,p′的最大公約數g′g'g′
最新式子兩邊繼續除以g′g'g′,直到(a,p′)=1(a,p')=1(a,p′)=1為止
在此過程中,假設取出來了cntcntcnt個aaa,出去公約數后剩下的乘積為a′a'a′
此時(a′,p′)=1(a',p')=1(a′,p′)=1,于是可以轉化為ax?cnta′≡b(modp)?ax?cnt≡b′(a′)?1(modp)a^{x-cnt}a'\equiv b\pmod p \Leftrightarrow a^{x-cnt}\equiv b'(a')^{-1}\pmod pax?cnta′≡b(modp)?ax?cnt≡b′(a′)?1(modp)
其中cntcntcnt表示兩邊除以最大公約數ggg的次數
此處右邊有逆元,為了避免求逆元,將a′a'a′保留在左邊
在BSGS枚舉左邊時,初始值設為a′a'a′即可
如果在除以ggg的過程中,發現b′(a′)?1=1?b′≡a′?x?cnt=0?x=cntb'(a')^{-1}=1\Leftrightarrow b'\equiv a'\Rightarrow x-cnt=0\Rightarrow x=cntb′(a′)?1=1?b′≡a′?x?cnt=0?x=cnt
接下來,直接套用基礎BSGS即可,記得最后的答案不要忘記加上cntcntcnt喲(^U^)ノ~YO
總結
以上是生活随笔為你收集整理的【学习笔记】原根 / BSGS / 扩展BSGS证明及模板的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一部手机一台电脑一部手机一台电脑如何在家
- 下一篇: excel怎么自动排序