1. 程式人生 > >Cipolla演算法學習小記

Cipolla演算法學習小記

簡介

Cipolla演算法是解決二次剩餘強有力的工具,一個腦洞大開的演算法。
認真看懂了,其實是一個很簡單的演算法,不過會感覺得出這個演算法的數學家十分的機智。

基礎數論儲備

二次剩餘

首先來看一個式子x2n(modp),我們現在給出n,要求求得x的值。如果可以求得,n為mod p的二次剩餘,其實就是n在mod p意義下開的盡方。Cipolla就是一個用來求得上式的x的一個演算法。

勒讓德符號

勒讓德符號是判斷一個數是否為p的二次剩餘的一個有力工具,p一定要為奇質數。(n,p)表示n為關於p的勒讓德符號。其實就是判斷n是否為p的二次剩餘。

(np)=1p
n,np
1pnnp0pn

看起來好像是一大段廢話,勒讓德只是站在巨人的肩膀上總結了一下而已。
其實勒讓德還總結了一些性質,不過一般只用得到尤拉判別準則,不夠勒讓德符號是個積性函式可能還有點用。
但還是不知道如何判斷n是否為p的二次剩餘,往下看尤拉判別準則

 ll Legendre(ll a, ll p)  
  {  
       return qsm(a, (p-1)/2, p);  
  } 

尤拉判別準則

先來回顧一下尤拉定理xφ(p)1(modp)
因為這裡的p是奇質數,所以x

p11(modp)
xp1進行開方操作,在虛數域中xp12±1(modp),如果等於1就肯定開的了方,為-1一定開不了。所以x是否為n的二次剩餘就用這個尤拉判別準則。

if(qsm(n,(p-1)/2)==p-1){
    printf("No root\n"); 
    continue;   
}

-1在mod p意義下為p-1。

演算法流程

給出n和p
就算我們n關於p的勒讓德符號為1,那麼要怎樣取開n的方呢?
現在是腦洞大開的時候。

找一個數a

我們隨機一個數a,然後對a2n進行開方操作(就是計算他勒讓德符號的值),直到他們的勒讓德符號為-1為止(就是開不了方為止)


就是找到一個a滿足(a2n)p12=1
先不要管為什麼,後面會講,我們現在就默默的去膜拜Cipolla的腦洞很大。

while(1){
    a=rand()%p;
    w=(a*a-n+p)%p;
    if(qsm(w,(p-1)/2)==p-1)break;
}

因為是隨機找a,那麼會不會要找很久。
答案:不會!
1x2n(modp)p12n使
1x2n(modp),如果存在不同的數u,v,使他們帶入x後可以使方程有解,那麼很顯然滿足u2v2|p,所以滿足(u+v)(uv)|p,因為
u2v2|p所以p不可能是(u-v)的倍數,所以(u+v)|p,那麼這樣的數對在p中存在的數量為p12
根據定理1,隨機找a的期望為2。

建立一個複數域

說是建立,其實根本不用程式去打,說是建立複數域只是跟方便理解。
在平常學的複數域中,有一個i,滿足i2=1
我們也建立一個類似的域,因為我們要對於a2n開方,而a2n有不是p的二次剩餘,所以我們定義ω=a2n。那麼現在的ω也像i一樣,滿足ω2=a2n,這樣我們就定義了一個新的域。

struct CN{
    ll x,y;
    CN friend operator *(CN x,CN y){
        CN z;
        z.x=(x.x*y.x%p+x.y*y.y%p*w%p)%p;
        z.y=(x.x*y.y%p+x.y*y.x%p)%p;
        return z;    
    }
}u,v;

像正常打複數運算一樣我們定義一下運算子。可以發現z.x那個地方後面是*w而不是*1,因為現在的域單位複數為ω,滿足

相關推薦

Cipolla演算法學習小記

簡介 Cipolla演算法是解決二次剩餘強有力的工具,一個腦洞大開的演算法。 認真看懂了,其實是一個很簡單的演算法,不過會感覺得出這個演算法的數學家十分的機智。 基礎數論儲備 二次剩餘 首先來看一個式子x2≡n(modp),我們現在給出n,要求

狄克斯特拉演算法學習小記

丟擲問題 在廣度優先搜尋演算法裡面我們在從雙子峰到金門大橋的圖裡面尋找的是換乘最短的路徑,但是我們需要找出最快的路徑應該怎麼選擇? 如下圖: 因此我們可以使用另一種演算法——狄克斯特拉演算法(Dijkstra’s algorithm)。 演算法簡介 狄克斯特拉演算法包含4個

Miller-Rabin及Pollard-Rho演算法學習小記

質數快速判斷演算法Miller-Rabin 不想詳細寫了,因為也不會證。 貼板子! bool Miller_Rabin(ll n){ if (n==1) return 0; i

SIFT演算法學習小記

作者:saintbird     Sift是David Lowe於1999年提出的區域性特徵描述子,並於2004年進行了更深入的發展和完善。Sift特徵匹配演算法可以處理兩幅影象之間發生平移、旋轉、仿射變換情況下的匹配問題,具有很強的匹配能力。在Mikolajczyk對包括S

bsgs(大步小步演算法)和exbsgs(擴充套件大步小步演算法)學習小記

翻譯: bsgs: baby steps,giant steps bsgs: 解決以下問題: 有三個整數a,b,p,其中p是質數。 求最小的自然數x,使ax=b(modp)ax=b(modp)。 根據費馬小定理,ap−1=1(modp)ap−1

堆排序演算法學習小記

1.完全二叉樹的概念       若設二叉樹的深度為h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第 h 層所有的結點都連續集中在最左邊,這就是完全二叉樹。      完全二叉樹是由滿二叉樹而引出來的。對於深度為K的

yarn 學習 小記

webp 清除 style conf comm project yarn info lin 官網:https://yarnpkg.com/zh-Hans/docs/installing-dependencies 簡介:包管理工具,和npm類似主要特點:快速、安全、可靠  快

selenium學習小記

statement from 都沒有 mat load 發現 runtest 打開 stat selenium用於頁面自動化測試,其簡介雲雲這裏不再粘來粘去的贅述,浪費時間。下面說說自己遇到的一點小問題,及其處理方法。 一:selenium安裝   安裝方法,百度一下,相比

學習小記:JS判斷時特殊值與boolean類型的轉換

ring something mbo true mage js框架 temp some .info 扒開JQuery以及其他一些JS框架源碼,常常能看到下面這樣的判斷, 寫慣了C#高級語言語法的我,一直以來沒能系統的理解透這段代碼。 var test; //do

Python學習小記

hang class 字典 code col shang alice hone sha 字典: 1. 1 people = { 2 ‘Alice‘:{ 3 ‘phone‘: ‘111‘, 4 ‘addr‘: ‘shangha

二維最小乘積生成樹學習小記

轉化 div 求解 idt pla 學習 right log inf Preface   對於形如給定一些邊,其邊權為xi和yi,構造一個生成樹,使得   我們稱這棵樹,為最小乘積生成樹。我們可以考慮,沿用最小生成樹的思想,把這種新穎的最小生成樹做對。 Conte

枚舉enum學習小記

AI 兩個 有關 pri AC 聲明變量 文件 參數 lis 參考文獻: [1]C++程序設計語言(特別版), 裘宗燕譯, 機械工業出版社 [2]C++ Primer (3rd Ed.), S.B. Lippman and J. Lajoie, 人民郵電出版社 1、枚舉

【2018/04/02】學習小記

webp style pac error 進度條 成功 .config lB lba 復習了webpack的一些基礎~ --progress 帶進度條 --watch 使用緩存 --colors 醒目標記 node_modules本地最好自己有一份(~ ̄(OO) ̄)ブ,要不

無監督學習小記(參考)

廣泛 個數 就是 sca 協方差矩陣 ear 元素 約束 方法 下面淩亂的小記一下無監督學習 無監督學習->聚類 降維 聚類:數據相似性 相似性的評估:兩個數據樣本間的距離 距離:歐氏距離 曼哈頓距離 馬氏距離 夾角余弦 sklearn 聚類算法 sklearn.cl

java集合類學習小記

lse 實例 hash 如果 集合 常用 遍歷 保存 bject 【List接口】:可變數組,允許保存所有類型元素,包括null,元素可重復,按添加順序保存【常用實現類】:建議用ArrayListArrayList:索引訪問速度快(但插入和刪除節點較慢)LinkedList

啟發式合並(堆、set、splay、treap)/線段樹合並學習小記

排序 需要 操作數 所有 class 兩個 因此 ext pan 啟發式合並 剛聽到這個東西的時候,我是相當蒙圈的。特別是“啟發式”這三個字莫名的裝逼,因此之前一直沒有學。 實際上,這個東西就是一個SB貪心。 以堆為例,若我們要合並兩個堆a、b,我們有一種極其簡單的做法:

BTM學習小記

color lda col src ram pen 估計 param sel BTM的原理跟LDA很像,下面是該模型的概率圖: 由該圖可以看出來,與LDA的區別在於確定主題分布和詞分布後相應地取兩個詞(而LDA只取一個,即類比常見的骰子說法:先投擲K面的骰子得到主題z,再

RocketMQ Consumer 負載均衡演算法學習 -- AllocateMessageQueueAveragelyByCircle

首先, RocketMQ Consumer 的負載均衡指的是把Topic 下的所有MessageQueue 分配到不同的 Consumer 中,所以Message Queue , Consumer 的數量,某個Consumer 的位置 會影響到負載均衡。 這邊介紹下環形平均分配的演算法:

[學習筆記] Berlekamp-Massey演算法 - 學習筆記

重新實現了一個看上去就像是對的的東西。 推薦:傳送門 講的很清楚了,不多贅述。 #include<bits/stdc++.h> #define gc getchar() #define rep(i,a,b) for(int i=a;i<=b;i++) #define R