日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

【转】初等数论 ——原根、指标及其应用

發布時間:2023/11/27 生活经验 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】初等数论 ——原根、指标及其应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://blog.163.com/gc_chdch@126/blog/static/172279052201641935828402/

?


?

學習總結:初等數論(3)——原根、指標及其應用??

2016-05-19 15:58:28|??分類:?信息學——學習總?|??標簽:初等數論??數學??|舉報|字號?訂閱

學習總結:初等數論(3)——原根、指標及其應用

?

最近知道了一本書叫《數論概論(第3版)》(A Friendly Introduction to Number Theory),簡單翻了翻,感覺這本書寫的非常好。想起以前剛接觸數論時,沒有看這本書來入門,真是十分遺憾。這本書面向非數學專業讀者,語言生動幽默而不失嚴謹性,注重對知識的感性認識(用了大量的例子),和對數學思想和方法的滲透(比如:大膽猜想規律,證明時用“計數”法等)。這里強烈推薦這本書!

?

下面總結一下這幾天學習的內容。

?

一、整數的階

a與n是互質的兩個數。可以發現,總存在某個數x,滿足?ax?≡ 1(mod?n)。

使ax?≡ 1(mod?n)滿足的最小的正整數x叫做a模n的階(或次數),記做ena(有的地方記做ordna)。

怎么理解呢?你要不斷計算a,a2,a3,…,(注意要模n)我們知道,根據鴿巢原理,一定會有循環。而a和n互質時,總會在某個時刻出現了1,下一個時刻又是a,……于是就有了循環。這個出現1的最小的指數,叫做a的階。

比如:我們要找3模7的階,計算31,32,…,36模7的值依次為:

3,2,6,4,5,1,

所以我們得到3模7的階為6。

?

a與n互質時,根據歐拉定理有a?(n)≡1(mod?n)。這么說來,剛才我們不斷計算a的冪的循環節的長度(即a的階)“擴增”若干次后應該為?(n)。所以,

ena?|??(n)。

同樣的道理,為了使方程?ax≡1(mod?n)有解,應該把循環節長度“擴增”若干次后得到x,所以

ena?|?x

?

二、原根

設a與n是互質的整數,當a模n的階為?(n)時,把a叫做n的原根。

怎么理解呢?我們計算a的冪的序列,第一次得到1的時候,得到了完整的一個循環節。我們上面已經說了,?(n)一定是(a模n的階)的倍數。如果這個循環節的長度恰好就是?(n)(循環節的長度已經達到最大了),那么a就是n的原根。

?

(1)原根的存在性

一個數可能有很多個原根,也可能沒有原根。可以證明:

正整數n存在原根,當且僅當

n?= 2, 4,?pt或2pt(其中p是奇素數,t是正整數)。

舉例:5的原根有2和3;7的原根有3和5。

?

(2)原根的一個性質

原根為什么這么重要?

設g是n的一個原根,那么:g,g2,g3,…,g?(n)(即g0≡1(mod?n))一定兩兩不同。(如果有相同,比如說存在0≤i<j<?(n)滿足gi≡gj(mod?n),那么就會有gj-i≡1(mod?n),而j?–?i<?(n),這時?(n)就不是g的階了)

看看方程ax≡1(mod?n),如果x是存在的,那么a一定是與n互質的數(如果a和n有某個大于1的公因子,無論a怎么取冪再模n,這個公因子都“消不掉”,不會有ax?mod?n?= 1)。所以“合法”的a有?(n)個。而我們找到一個原根g后,g的冪(g,g2,g3,…,g?(n))一定就是這些合法的a(即與n互質的?(n)個數。因為g與n互質,g的冪也與n互質,而這些冪又兩兩不同,一定能把“與n互質的數”取盡)。

一句話總結上面的內容:對于n的一個原根g,滿足

{ 1,g,g2,g3,…,g?(n) – 1?} = {?x?|?x與n互質,1≤x<n?}

特別地,對于奇質數p的一個原根g,滿足

{ 1,g,g2,g3,…,gp?– 2?} = { 1, 2, 3, …,?p?– 1 }

(3)原根的個數

一個數n,如果存在原根,就一定?(?(n))個。怎么證明呢?為此我們先討論下面這個問題:

?

已知a模n的階ena,怎么求au的模n的階?

設au模n的階為t,那么t應該是最小的正整數,滿足(au)t≡aut≡1 (mod?n)。

由之前的討論,可以知道:u×t應該是ena的倍數,并且t最小。

由數論的基本知識可以得出,enau?=?t?=?ena?/ gcd(u,?ena)。

?

如果我們找出一個原根g,怎么得出其他的原根?

首先,其他的原根一定是g的若干次冪。

哪些“g的若干次冪”可以成為原根?

用原根的定義!

對于某個“g的若干次冪”,比如gi?(0≤i<?(n)),由上面的結論得出,它模n的階為

?(n) / gcd(i,??(n))

欲使它的階也為?(n),即

?(n) / gcd(i,??(n)) =??(n)

需要使gcd(i,??(n)) = 1,也就是i和?(n)互質。

有多少個i滿足它和和?(n)互質?換句話說,在0 ~??(n)–1的數中,有多少個與?(n)互質?答案應該是?(?(n))。所以,一個數如果有原根,那么它有?(?(n))個原根。

?

下面舉個例子:

7的原根有?(?(7)) =??(6) = 2個,最小的一個是3。

在32,33,…,36中,哪個指數與6互質?只有5,所以另一個原根是35≡5(mod 7)。

?

怎么找原根?

通常最小的原根都比較小,所以暴力從1開始枚舉就可以了。判斷一個數a是不是n的原根,需要判斷?(n)是否是a的階,直接的判斷方法是枚舉?(n)的每一個因子d(除去它本身),判斷是否ad≡1(mod?n)。但這樣做了很多重復的判斷。

比如我們要判斷a模n=37的階是否為36,那么只需找出36的兩個質因子2和3,只需判斷36/2和36/3作為a的冪的指數時,(a的冪) mod?n是否為1。如果a的階為36/4,36/9,36/6,36/12,…,其實情況已經包含在上面的判斷中了。(比如,如果a36/9≡a4≡1(mod?n),那么一定也會滿足a36/2≡3618≡1(modn))。

?

三、指標(離散對數)

求原根有什么作用?為了計算指標!

對于n的一個原根g,滿足

{ 1,g,g2,g3,…,g?(n) – 1?} = {?x?|?x與n互質,1≤x<n?}

再具體一些,可以定義一種“求冪”的運算,這種運算揭示了兩個集合的一一對應關系:

i?→?gi?(1≤i≤?(n))

為什么是一一對應關系?因為gi一定兩兩不同。這一點已經討論過了。

?

那么,是否有一種“求冪”運算的逆運算?有!

求出n的一個原根g,知道了某個與n互質的數a,n是g的多少次方?

我們用I(a)來表示這個“次方”數,叫做以g為底a模n的指標。(有的地方記做indga)

也就是,依照定義,應該有gI(a)≡a(mod?n)(a與n互質)。

顯然,指標的范圍是0≤I(a)<?(n),當指標超過?(n)時,出現了循環,可以把指標mod??(n)進行簡化。

有點像我們以前學過的對數?(不嚴謹的說,有點像logga?)也許這就是為什么指標也叫離散對數了。

?

當n為質數時,原根g一定存在,而且?(n) =?n?– 1,這樣,每個在1~n–1范圍內的數都有指標!

?

我們可以根據冪的運算法則,對應得出指標的運算法則:

(1)?I(ab) =?I(a) +?I(b) (mod??(n)) ?(類比:logaNM?= logaN?+ logbM)

(2)?I(ak) =?k×I(a) ? (類比:logaNM?=?M×logaN)

指標把乘法變加法,把冪變乘法,這一點與對數的運算法則多么相似!

?

如果有一個指標表,我們可以十分簡便地進行運算。舉例:

n?= 37,它的一個原根是a?= 2。

要計算23×19 mod 17的值,可以計算

I(23×19) ≡?I(23) +?I(19) ≡ 15 + 35 ≡ 50 ≡ 14 (mod 36)

然后,查表可以得出,指標為14的數是30,就是要求的答案了。

很麻煩?

再看一個例子:

I(2914) ≡ 14 ×?I(29) ≡ 294 ≡ 6 (mod 36)

由表得:I(27) = 6,所以2914?≡ 27 (mod 37) ?

你也許會說:有快速冪!在前兩個例子中,似乎指標的優勢沒有體現出來。不過,在解方程的時候,指標就很有用了。

解同余式:

擴展歐幾里得?好像也能解。不過,像下面這樣的同余式呢?

只能用指標來解。兩邊同時求離散對數:

可以解出:

事實上,最后一個例子是指標最重要的運用之一。等會兒我們會詳細討論。

?

但是,之前的計算都是在指標表已經給了的情況下進行的。沒有指標表怎么辦呢?如何求某個數指標(離散對數)?

更準確地說,給出g,?a,?p,如何求gk?≡?a(mod?p)的最小的k?為了簡化問題,這里規定p為質數。

這里使用一種叫做大步小步(gaint-step?baby-step)的算法。算法的核心思想是分塊。取m?= [ sqrt(p?– 1) ] + 1,然后把k表示成xm?+?y?(0 ≤?y?<?m)的形式。這樣,x和y的范圍都是0~m(y不含m)。于是gk?≡ (gm)x?×?gy,可以求出所有的gy(m個取值);然后枚舉x,計算出(gm)x,查找:是否存在某個gy滿足(gm)x?×?gy?≡?a(mod?p)?也就是說:

是否存在某個gy,滿足gy?≡?a?× (gmx)?–1?(mod?p)?

用費馬小定理和快速冪求出逆元(gmx)?–1,然后求出a?× (gmx)?–1。檢查是否有“匹配”的gy。如果我們先把gy放在一個哈希表(或者C++的map)中,那么這一步的查詢就是O(1)(或O(log2m)=O(log2p))的。算法的核心步驟仍然是枚舉,但分塊使時間復雜度變成O(sqrt(P) × log2P)(注意算上求逆元的時間)。

?

四、N次剩余

這里要解決一個這樣的問題:

給出N,?a,?p,求滿足xN?≡?a?(mod?p)(p為質數)的所有解x。

可以形象地理解成求a在模p意義下的N次方根。

?

剛才我們已經借助例子,初步了解了做法:

xN?≡?a?(mod?p),找出p的一個原根g,用“大步小步”算法求出以g為底a模p的指標I(a)。

同余式變成:

N?×?I(x) ≡?a?(mod?p?– 1)

?

由一次同余方程的知識可以知道,有解的條件是

gcd(N,?p?– 1) |?a

而且,解有gcd(N,?p?– 1)個。

?

解出所有的可能的I(x),那么x?=?gI(x)。這些x中重復的要去掉。

?

代碼:

#include ?<cstdio>

#include ?<cstring>

#include ?<algorithm>

#include ?<cmath>

#include ?<vector>

#include ?<map>

using ?namespace std;

?

typedef ?long long LL;

?

int ?gcd(int a, int b)

{

? return b == 0 ? a : gcd(b, a % b);

}

?

void ?_gcd(int a, int b, LL &x, LL &y)

{

? if (b == 0)

? {

? ? ? x = 1; y = 0;

? ? ? return ;

? }

? _gcd(b, a%b, y, x);

? y -= (a/b) * x;

}

?

int ?extend_gcd(int a, int b, int c, LL &x, LL &y, int &dx, int ?&dy)

{

? int g = gcd(a, b);

? if (c % g) return 0;

? _gcd(a, b, x, y);

? x *= (c/g);

? y *= (c/g);

? dx = b / g;

? dy = a / g;

? return g;

}

?

// Ax ?= B (mod N)

//?設Ax = ?-yN + B

//?則Ax + ?Ny = B

bool ?line_mod_equ(int A, int B, int N, int &x, int &k)

{

? LL x0, y0;

? int dx, dy;

? if (!extend_gcd(A, N, B, x0, y0, dx, dy)) ?return false;

? x0 %= dx;

? if (x0 < 0) x0 += dx;

? x = (int)x0;

? k = dx;

? return true;

}

?

LL ?pow_mod(LL a, LL b, LL p)

{

? if (b == 0) return 1;

? LL tmp = pow_mod(a, (b>>1), p);

? if (b & 1) return tmp * tmp % p * a % ?p;

? ? ? else return tmp * tmp % p;

}

?

//分解質因數

void ?factor(int x, vector<int> &divs)

{

? divs.clear();

? for (int i = 2; i * i <= x; ++ i)

? ? ? if (x % i == 0)

? ? ? {

? ? ? ? ?divs.push_back(i);

? ? ? ? ?while (x % i == 0) x /= i;

? ? ? }

? if (x > 1) divs.push_back(x);

}

?

bool ?g_test(int g, vector<int> &divs, int P)

{

? for (int i = 0; i < (int) divs.size(); ?++ i)

? ? ? if (pow_mod(g, (P-1) / divs[i], P) == ?1) return false;

? return true;

}

?

//找原根,p為質數,保證有原根

int ?primitive_root(int P)

{

? static vector<int> divs;

? factor(P-1, divs);

? int g = 1;

? while (!g_test(g, divs, P)) ++ g;

? return g;

}

?

//?求解在模P意義下,以a為底N的離散對數b (P為質數)

//?即?a ^ b ?= N (mod P)

//?大步小步算法(分塊)

//?取s = ?sqrt(P),?設b = x * s + y

//?則?a ^ ?(x*s + y) = (a^s)^x * a^y = N (mod P)

//?求出y = ?0~s-1時,?a^y的取值;然后枚舉s,算出(a^s)^x,查找是否有匹配的y

int ?discrete_log(int a, int N, int P)

{

? map<int, int> rec;

? int s = (int)sqrt(P + 0.5);

? while (s * s <= P) ++ s;

? LL cur = 1;

? for (int y = 0; y < s; ++ y)

? {

? ? ? rec[ cur ] = y;

? ? ? cur = cur * a % P;

? }

? LL a_s = cur; // a^s

? cur = 1;

? for (int x = 0; x < s; ++ x)

? {

? ? ? LL a_y = pow_mod(cur, P-2, P) * LL(N) % ?P;

? ? ? map<int,int> :: iterator it = ?rec.find( a_y );

? ? ? if (it != rec.end()) return x * s + it ?-> second;

? ? ? cur = cur * a_s % P;

? }

? return -1;

}

?

// x ^ ?K = A (mod P) (where P is a prime)

//?找p的一個原根g,求出指標

// K ?I(x) = I(A) (mod P-1)

//?有解的條件?gcd( ?I(x), P-1 ) | I(A)

void ?discrete_root(int K, int A, int P, vector<int> &x)

{

? x.clear();

? if (A == 0) { x.push_back(0); return ; }

? int g = primitive_root(P);

? int IA = discrete_log(g, A, P);

? int Ix, delta;

? if (!line_mod_equ(K, IA, P-1, Ix, delta)) ?return ;

? while (Ix < P)

? {

? ? ? x.push_back( pow_mod(g, Ix, P) );

? ? ? Ix += delta;

? }

? sort(x.begin(), x.end());

? x.erase(unique(x.begin(), x.end()), ?x.end());

}

?

int ?main()

{

? int P, K, A;

? scanf("%d%d%d", &P, &K, ?&A);

? static vector<int> x;

? discrete_root(K, A, P, x);

? printf("%u\n", x.size());

? for (int i = 0; i < (int) x.size(); ++ ?i) printf("%d\n", x[i]);

? return 0;

}

?


2016-09-06?20:59:38

轉載于:https://www.cnblogs.com/Konjakmoyu/p/5847136.html

總結

以上是生活随笔為你收集整理的【转】初等数论 ——原根、指标及其应用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。