3月12日 二次剩餘(shanks解法)

2021-08-16 20:19:08 字數 1812 閱讀 2883

演算法原理請wiki:tonelli–shanks algorithm,迅速深入理解是不太可能的,與cipola演算法相比,shanks解法更數論一點。

(這個演算法是正常的,但是還是tle)

大概流程是: r2

≡nmodp

r 2≡

nmod

p令p−

1=q2

s p−1

=q2s

其中q是奇數。若s=1,即p≡

3mod

4 p≡3

mod4

由尤拉判定直接解出r≡

np+1

4mod

p r≡n

p+14

modp

對於其他情況,隨機選擇乙個z(這個跟cipolla很像),使得(z

p)=−

1 (zp

)=−1

,令c≡

zqmodp

c ≡z

qmod

p,並令r≡

nq+1

2 r≡n

q+12

t≡nq t≡n

qm=s

m =s

(1)若t≡

1 t≡

1,r就是乙個解,另乙個解是p-r。

(2)否則,找乙個最小的i,

0<

i<

i<

m,使得t2i

≡1t 2i

≡1

令b≡c2m−

i−1 b≡c

2m−i

−1

,r≡rb r≡r

b,t

≡tb2

t ≡t

b2

,c≡b2 c≡b

2,m

=im =i

,重複(1)。

#include

#include

#include

#include

using namespace std;

#define ll long long

ll qp(ll a, ll b, ll p)

return tmp;

}ll le(ll n, ll p)

ll solve(ll n, ll p)

if (s == 1)

ll z;

while (true)

ll c = qp(z, tp, p);

ll r = qp(n, (tp + 1) >> 1, p), t = qp(n, tp, p), m = s;

while (true)

ll po = 1;

for (int i = 1; i <= m - i - 1; i++)po <<= 1;

ll b = qp(c, po, p);

// ll b=qp(c,1

<<(m-i-1),p);

r = r*b

%p; t = t*b

*b%p;

c = b*b

%p; m = i;

}return0;}

int main()

if (le(n, p) + 1 == p)

ll a = solve(n, p);

ll b = p - a;

if (a > b)std::swap(a, b);

if (a == b)

else

printf("%lld

%lld\n", a, b);

}return

0;}

二次剩餘小結

對於模數 n 和整數 a 若存在整數 x 滿足 x 2 equiv a mod n 則稱 x 是模 n 意義下的二次剩餘,否則是非二次剩餘 注 這裡討論的 x 滿足 x in 1,n 尤拉判別法 對於奇素數 p a 是模 p 意義下的二次剩餘當且僅當 a equiv 1 mod p 類似的,若 a ...

二次剩餘小記

看 text 的部落格看到的,發現似乎並沒有想象中的那麼難,就學了一下,過了板題,這裡記錄一下,暫時還是只會二次剩餘,n 次剩餘暫時先放一下。下文的 p 即是模數。我們稱 n 為模 p 意義下的二次剩餘當且僅當存在 x 使得 x 2 equiv n pmod p,x in mathbb 下文的 ma...

二次剩餘雜記

參考資料一 參考資料二 對於 x 和 p 如果存在 a in 0,p 滿足 a 2 equiv x pmod p 則稱x為模 p 的二次剩餘。在這裡,我們暫時只討論 p 為奇素數的情況。有乙個性質,二次剩餘與非二次剩餘的個數均為 frac 2 如果 p 的原根為 g 那麼 g 的偶數次冪顯然都是二次...