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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

中高级数论 [欧拉函数线性筛,二次剩余]

發(fā)布時(shí)間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 中高级数论 [欧拉函数线性筛,二次剩余] 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

歐拉函數(shù)線性篩

對于素?cái)?shù)ppp,
φ(p?i)={p?1i=1p?φ(i)p∣i(p?1)?φ(i)p?i\varphi (p*i)= \begin{cases} p-1& i=1\\ p*\varphi(i)& p \mid i\\ (p-1)*\varphi(i) & p \nmid i \end{cases}φ(p?i)=??????p?1p?φ(i)(p?1)?φ(i)?i=1pip?i?

證明:

i=1i=1i=1 顯然

i≠1i \neq1i?=1根據(jù)

φ(i)=i∏pi?1pi\varphi(i)=i \prod \frac {p_i-1}{p_i}φ(i)=ipi?pi??1?

p∣ip \mid ipi時(shí)除掉iii中的ppp

p?ip \nmid ip?i 時(shí)除掉ppp

魔改歐拉篩素?cái)?shù)即可

歐拉定理

當(dāng)(a,p)=1(a,p)=1(a,p)=1

aφ(p)≡1(modp)a^{\varphi(p)}\equiv 1 \pmod paφ(p)1(modp)

ab≡ab%φ(p)(modp)a^{b}\equiv a^{b\%\varphi(p)} \pmod pabab%φ(p)(modp)

擴(kuò)展歐拉定理

當(dāng)b≥φ(p)b\geq\varphi(p)bφ(p)

ab≡ab%φ(p)+φ(p)(modp)a^{b}\equiv a^{b\%\varphi(p)+\varphi(p)} \pmod pabab%φ(p)+φ(p)(modp)

注意不要求互質(zhì)

Miller Rabbin 算法

可以O(logx)O(log_x)O(logx?)判斷素?cái)?shù)(有極小概率出錯(cuò))

費(fèi)馬小定理:ppp為素?cái)?shù),a≠pa \neq pa?=p,ap?1≡1(modp)a^{p-1} \equiv 1 (mod \text{ } p)ap?11(mod?p)

我有一個(gè)對這個(gè)命題的十分美妙的證明,可惜這里空白太小,我寫不下

二次探測定理:ppp為素?cái)?shù),x2≡1(modp)x^2 \equiv 1 (mod\text{ } p)x21(mod?p)的解為x=1x=1x=1x=p?1x=p-1x=p?1

證明見二次剩余

算法流程:設(shè)要判斷的數(shù)為xxx

  • 特判0,1,20,1,20,1,2,偶數(shù)
  • 取一個(gè)較小素?cái)?shù)ppp,設(shè)a,ba,ba,b滿足2a×b=x?12^a \times b=x-12a×b=x?1
  • 設(shè)x′≡pb(modx)x' \equiv p ^ b (mod \text{ } x)xpb(mod?x),不斷取平方并對xxx取模,若結(jié)果為111,用二次探測判斷。
  • 重復(fù)aaa次后x′≡px?1(modx)x' \equiv p ^ {x-1} (mod \text{ } x)xpx?1(mod?x),用費(fèi)馬小定理判斷
  • 例題:hdu2138 How many prime numbers

    題意:給NNN個(gè)數(shù),數(shù)數(shù)有多少個(gè)素?cái)?shù)

    #include <iostream> #include <cstdio> #include <cstring> #include <cctype> typedef long long ll; using namespace std; int qpow(int a,int p,int m) {int ans=1;while (p){if (p&1) ans=((ll)ans*a)%m;a=((ll)a*a)%m,p>>=1;}return ans; } int pri[]={2,3,5,7,11,13,17,19,23,29}; bool check(int x) {if (x==2) return true;if (!(x&1)) return false;int a=0,b=x-1;while (!(b&1)) ++a,b>>=1;for (int i=0;pri[i]<x&&pri[i]<29;i++){int now=qpow(pri[i],b,x);for (int j=1;j<=a;j++){int t=((ll)now*now)%x;if (t==1&&now!=1&&now!=x-1) return false;now=t;}if (now!=1) return false;}return true; } int main() {int n;while (~scanf("%d",&n)){int ans=0,x;while (n--){scanf("%d",&x);ans+=check(x);} printf("%d\n",ans);}return 0; }

    關(guān)于底數(shù)選擇:

    2,3,7,61,242512,3,7,61,242512,3,7,61,24251為底,1e161e161e16內(nèi)唯一無法判斷的合數(shù)為468562482559814685624825598146856248255981

    特判一下就可以了

    代碼不想改了

    Pollard-Rho算法

    這個(gè)算法就更玄學(xué)了,可以極快分解質(zhì)因數(shù)。

    有多快呢?longlonglong \text{ }longlong?long能跑幾百個(gè)

    該算法核心是找到這個(gè)數(shù)的一個(gè)非平凡因子(即不是111和本身,以下簡稱因子),然后遞歸就行了

    如何找到一個(gè)因子呢? 隨機(jī)。

    當(dāng)然直接隨機(jī)肯定不現(xiàn)實(shí),需要一定的改進(jìn)

    ①優(yōu)秀的隨機(jī)函數(shù)

    定義隨機(jī)函數(shù)fi=fi?12+cf_i=f_{i-1}^2+cfi?=fi?12?+c,其中ccc為隨機(jī)常數(shù)。

    至于為什么要選這個(gè)函數(shù)……鬼知道啊

    gcdgcdgcd

    設(shè)給定的數(shù)為xxx,我們要找的是d∣xd \mid xdx

    概率還是低了點(diǎn)

    容易想到一個(gè)辦法:取gcdgcdgcd,大于111就返回gcdgcdgcd的值

    這樣多了因數(shù)的倍數(shù),很大的提高了概率

    ③倍增路徑

    每次取一段2k2^k2k個(gè)數(shù),在模xxx乘起來,最后取gcdgcdgcd,kkk為當(dāng)前段數(shù)

    易知這樣是等效的,避免了大量的gcdgcdgcd計(jì)算

    使用了倍增,將gcdgcdgcd次數(shù)從O(n)O(n)O(n)降至O(logn)O(logn)O(logn)

    另外不再使用隨機(jī)值,而是用隨機(jī)出來的值和上一段最后一個(gè)數(shù)作差,這樣得到數(shù)的個(gè)數(shù)也大幅增加。

    這樣除非環(huán)特別短,否則環(huán)上兩兩的數(shù)都會(huì)統(tǒng)計(jì)入答案。

    根據(jù)生日悖論,當(dāng)環(huán)長為45時(shí)找不到答案的概率小于1e?181e-181e?18

    而你的函數(shù)是根據(jù)CCC改變的,所以根本卡不了

    所以如果出鍋了,自覺去交一發(fā)Hash Killer III

    ④玄學(xué)優(yōu)化

    每一段跑127127127個(gè)數(shù)更新一次

    親測快了333

    來自luoguluoguluogu題解區(qū)

    原理就不得而知了

    結(jié)合Miller?RabbinMiller-RabbinMiller?Rabbin食用更佳

    例題:luogu模板

    題意:給個(gè)數(shù),是素?cái)?shù)輸出"Prime",不是素?cái)?shù)輸出最大質(zhì)因數(shù)

    遞歸,記個(gè)全局變量。還可以剪枝。

    運(yùn)用你豐富的卡常技巧就可以通過此題

    // luogu-judger-enable-o2 #include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <cstdlib> #ifdef WIN32 #define lld "%I64d" #else #define lld "%lld" #endif typedef long long ll; using namespace std; inline ll read() {ll ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans; } ll base[]={2,3,7,61,24251}; inline ll qmul(const ll& a,const ll& b,const ll& m) {ll ans=a*b-(ll)((long double)a*b/m+0.5)*m;return ans<0? ans+m:ans; } inline ll qpow(ll a,ll p,const ll& m) {ll ans=1;while (p){if (p&1) ans=qmul(ans,a,m);a=qmul(a,a,m),p>>=1;}return ans; } inline bool Miller_Rabbin(const ll& x) {if (x==1) return false;if (x==2) return true;if (!(x&1)) return false;if (x==46856248255981ll) return false;int a=0;ll b=x-1;while (!(b&1)) ++a,b>>=1;for (register int i=0;i<5&&base[i]<x;i++){ll now=qpow(base[i],b,x);for (register int j=1;j<=a;j++){ll t=qmul(now,now,x);if (t==1&&now!=1&&now!=x-1) return false;now=t;}if (now!=1) return false;}return true; } ll ans; inline ll f(const ll& x,const ll& c,const ll&m){return (qmul(x,x,m)+c)%m;} inline ll gcd(ll x,ll y) {static ll t;while (y>0) t=y,y=x%y,x=t;return x; } inline ll abso(const ll& x){return x>0? x:-x;} inline ll Pollard_rho(const ll& x) {ll s=0,t=0,c=rand()%(x-1)+1,d,len=1,m=1,i;for (;;len<<=1,s=t,m=1){for (i=1;i<=len;i++){t=f(t,c,x);m=qmul(m,abso(t-s),x);if (i%127==0&&(d=gcd(m,x))>1) return d;}if ((d=gcd(m,x))>1) return d;} } inline void fact(const ll& x) {if (x<ans) return;if (Miller_Rabbin(x)) return (void)(ans=max(ans,x));ll d=Pollard_rho(x);if (Miller_Rabbin(d)) ans=max(ans,d);else fact(d);d=x/d;if (Miller_Rabbin(d)) ans=max(ans,d);else fact(d); } int main() {register int T;ll n,d;scanf("%d",&T);while (T--){n=read();ans=0,fact(n),d=ans;if (n==d) printf("Prime\n");else printf(lld"\n",ans);}return 0; }

    原根

    占個(gè)坑以后補(bǔ)

    二次剩余

    以下的ppp均為奇素?cái)?shù)

    定義:方程x2≡n(modp)x^2 \equiv n (mod \text{ }p)x2n(mod?p)有解,稱nnnmodpmod \text{ } pmod?p意義下的二次剩余,否則稱非二次剩余

    說人話:在modpmod \text{ } pmod?p下可以開根號

    勒讓德符號

    (np)={1n是p的二次剩余?1n是p的非二次剩余0p∣n(\frac{n}{p})= \begin{cases} 1& \text{n是p的二次剩余}\\ -1& \text{n是p的非二次剩余}\\ 0 & p \mid n \end{cases}(pn?)=??????1?10?np的二次剩余np的非二次剩余pn?

    如無特別說明,下文分?jǐn)?shù)+括號均為勒讓德符號

    引理

    (np)≡np?12(modp)(\frac{n}{p}) \equiv n^{\frac{p-1}{2}} (mod \text{ }p)(pn?)n2p?1?(mod?p)

    (強(qiáng)調(diào):ppp是奇素?cái)?shù))

    證明:

  • 當(dāng)nnnppp的二次剩余,設(shè)x2≡n(modp)x^2 \equiv n (mod \text{ } p)x2n(mod?p),則np?12≡xp?1(modp)n^{\frac{p-1}{2}} \equiv x^{p-1} (mod \text{ } p)n2p?1?xp?1(mod?p)。由費(fèi)馬小定理,xp?1≡1(modp)x ^{p-1} \equiv 1 (mod \text{ } p)xp?11(mod?p)
  • 當(dāng)nnnppp的非二次剩余,即不存在x2≡n(modp)x^2 \equiv n (mod \text{ } p)x2n(mod?p)。對于任意的aaa,由于a2≠n(modp)a^2 \neq n (mod \text{ } p)a2?=n(mod?p),所以a≠a?1na \neq a^{-1}na?=a?1n。而逆元是互逆的,這樣可以把p?1p-1p?1個(gè)數(shù)配成p?12\frac{p-1}{2}2p?1?對,每對數(shù)的積為nnn。將所有數(shù)乘起來,(p?1)!≡np?12(modp)(p-1)! \equiv n^{\frac{p-1}{2}} (mod \text{ } p)(p?1)!n2p?1?(mod?p)。由威爾遜定理,(p?1)!≡?1(modp)(p-1)! \equiv -1 (mod \text{ } p)(p?1)!?1(mod?p)
  • p∣np \mid npn,顯然成立
  • 引理

    共有p?12\frac {p-1}{2}2p?1?個(gè)nnnppp下的二次剩余

    證明:設(shè)兩個(gè)數(shù)u,vu,vu,v滿足u≠v,u2≡v2(modp)u \neq v, u^2 \equiv v^2 (mod \text{ } p)u?=v,u2v2(mod?p),即p∣u2?v2=(u+v)(u?v)p \mid u^2-v^2=(u+v)(u-v)pu2?v2=(u+v)(u?v)

    p∣u+vp \mid u+vpu+v,反之同理

    說人話:有且僅有模意義下的相反數(shù)平方相同。

    所以x2x^2x2共有p?12\frac {p-1}{2}2p?1?個(gè)不同取值

    所以隨機(jī)出一個(gè)(非)二次剩余是O(1)O(1)O(1)

    引理

    (a+b)p≡ap+bp(modp)(a+b)^p\equiv a^p+b^p (mod \text{ } p)(a+b)pap+bp(mod?p)

    二項(xiàng)式定理展開即可,不再證明。

    重頭戲開始。坐穩(wěn)了,前方高能!

    隨機(jī)一數(shù)aaa,若(a2?np)=?1(\frac{a^2-n}{p})=-1(pa2?n?)=?1,令w=a2?nw=\sqrt{a^2-n}w=a2?n?,則(a+w)p+12(a+w)^\frac{p+1}{2}(a+w)2p+1?是方程x2≡n(modp)x^2 \equiv n (mod \text{ } p)x2n(mod?p)的根

    什么?a2?na^2-na2?n不是非二次剩余嗎?怎么開根?

    沒辦法啊……那就類比虛數(shù),定義z=a+bwz=a+bwz=a+bw吧(絕對不是人想出來的)

    引理

    wp≡?w(modp)w^p\equiv -w(mod \text{ } p)wp?w(mod?p)

    證明:wp≡wp?1w≡(a2?n)p?12w≡(a2?np)w≡?w(modp)w^p \equiv w^{p-1}w \equiv (a^2-n)^\frac{p-1}{2} w\equiv (\frac{a^2-n}{p})w\equiv -w (mod \text{ }p)wpwp?1w(a2?n)2p?1?w(pa2?n?)w?wmod?p

    最后證明:

    x2≡(a+w)p+1≡(a+w)p(a+w)≡(ap+wp)(a+w)=(a?w)(a+w)=a2?w2≡n(modp)x^2\equiv (a+w)^{p+1}\equiv (a+w)^p(a+w) \equiv (a^p+w^p)(a+w)=(a-w)(a+w)=a^2-w^2\equiv n(mod \text{ } p)x2(a+w)p+1(a+w)p(a+w)(ap+wp)(a+w)=(a?w)(a+w)=a2?w2n(mod?p)

    證畢……

    哎等等?xxx是虛數(shù)怎么辦?

    假設(shè)xxx是虛數(shù),設(shè)x=a+bwx=a+bwx=a+bw(不是上面的aaa) 由xxx定義,a≠0a \neq 0a?=0

    x2=a2+b2w2+2abw=a2+a2b2?nb2+2abwx^2=a^2+b^2w^2+2abw=a^2+a^2b^2-nb^2+2abwx2=a2+b2w2+2abw=a2+a2b2?nb2+2abw是虛數(shù),而nnn是實(shí)數(shù)。

    假設(shè)不成立,所以xxx是實(shí)數(shù)(并不嚴(yán)謹(jǐn))

    例題:Timus OJ1132 Square Root

    數(shù)據(jù)很小,暴力能過。但只有這題,將就了吧。

    #include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <cstdlib> #define int long long using namespace std; struct complex{int x,y;}; int n,w2,p; inline complex operator *(const complex& a,const complex& b){return (complex){(a.x*b.x%p+a.y*b.y%p*w2%p)%p,(a.x*b.y%p+a.y*b.x%p)%p};} inline complex qpow(complex a,int b) {complex ans;ans.x=1,ans.y=0;while (b){if (b&1) ans=ans*a;a=a*a,b>>=1;}return ans; } inline int qpow(int a,int b) {int ans=1;while (b){if (b&1) ans=ans*a%p;a=a*a%p,b>>=1;}return ans; } inline int lerender(const int& x){return qpow(x,p>>1);} int solve() {if (lerender(n)==p-1) return -1;int a;while (true){a=rand()%p;w2=(a*a-n)%p;if (w2<0) w2+=p;if (lerender(w2)==p-1) break;}complex res;res.x=a,res.y=1;res=qpow(res,(p+1)>>1);return res.x; } inline int read() {int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans; } void write(const int& x) {if (x<10) return(void)putchar(x^48);int t=x/10;write(t),putchar((x-(t<<1)-(t<<3))^48); } main() {int T=read();while (T--){n=read(),p=read();if (p==2) {printf("1\n");continue;}int ans=solve();if (ans==-1) printf("No root\n");else{int ans2=p-ans;if (ans>ans2) swap(ans,ans2);write(ans),putchar(' '),write(ans2),putchar('\n');}}return 0; }

    總結(jié)

    以上是生活随笔為你收集整理的中高级数论 [欧拉函数线性筛,二次剩余]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。