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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数论基础入门

發布時間:2023/12/31 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数论基础入门 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一些知識

整除

自然數a可以被自然數b整除或者說b是a的約數表示的是:
a%b=0a\%b=0a%b=0,即a是b的倍數,b是a的約數(不要弄反了),記作b|a。
(0是自然數也是整數)

質數(素數)和合數

指在大于1的自然數中,除了1和它本身不再有其他因數的自然數(如:2,3,5);一個大于1的整數,如果除了1和它本身以外,還有其他的約數,這樣的數就叫作合數。

素數的分布

目前素數的分布還不能確定,但是能夠給出一個近似分布,π(n)\pi(n)π(n)為不超過n的質數的個數,π(n)~nlnn\pi(n) \sim \frac{n}{lnn}π(n)lnnn?
證明灰常的復雜,感興趣的可以看這里

質因數

對于給定的自然數n,x是其質因數,當且x是n的因數且x是質數。

最大公因數

記作gcd()。

最小公倍數

記作lcm()。

互質

如果兩個或兩個以上的整數的最大公約數為1,則他們互質,記作a⊥ba \bot bab

唯一分解定理

任何一個大于1的數都可以被分解為有限個質數乘積的形式,并且分解方式是唯一的,
質數是一個整數最基本的特征,很多問題都從質數的角度考慮
如:300=22355 12=223
一個結論:
a=q1n1q2n2a=q_1^{n_1} q_2^{n_2}a=q1n1??q2n2??,且b|a,則b=q1b1q2b2b=q_1^{b_1} q_2^{b_2}b=q1b1??q2b2??,且bi大于等于0,小于與等于nib_i大于等于0,小于與等于n_ibi?0ni?
對于下圖中的約束,對應約束個數:
(來源參考)

約束個數中加一是考慮了還有1

完全平方數

若一個數能表示成某個整數的平方的形式,則稱這個數為完全平方數。

例題

求解兩個數最大公因數

如果暴力求解的話,即從一開始遍歷,復雜度為O(mina,b)O(min{a,b})O(mina,b);而歐幾里得算法(輾轉相除法復雜度可化簡為O(logn)O(logn)O(logn)

定理

gcd(a,b)=gcd(b,r),其中r為a/b的余數
嚴格的邏輯證明這里省略,簡單的說下思路:
假設gcd(a,b)=c, 那么假設a=k1c,b=k2ca=k_1c,b=k_2ca=k1?c,b=k2?c,a/b=k…ra/b=k…ra/b=kr,則r=a?bk=k1c?bk2c=(k1?bk2)cr=a-bk=k_1c-bk_2c=(k_1-bk_2)cr=a?bk=k1?c?bk2?c=(k1??bk2?)c,即可以得到r也是c的倍數,還要說明c是r和b的最大公因數,
現在b=k2cb=k_2cb=k2?c,r=(k1?bk2)cr=(k_1-bk_2)cr=(k1??bk2?)c,需要證明k2和(k1?bk2)k_2和(k_1-bk_2)k2?(k1??bk2?)互質,可以用反證法,如果不互質的話,會存在一個比c大的公因數,矛盾,所以不成立。

代碼

int gcd(int a,int b) {return b==0? a:gcd(b,a%b); } //b=0的時候,假如gcd(6,3),那么下一步遞歸得到gcd(3,0)即為3

補充性質

gcd(ka,kb)=kgcd(a,b)gcd(ka,kb)=k gcd(a,b)gcdka,kb=kgcd(a,b)
lcm(a,b)=a?bgcd(a,b)lcm(a,b)=\frac{a*b}{gcd(a,b)}lcm(a,b)=gcd(a,b)a?b?

素數判定

枚舉是否含有除了1和本身的因數,其實只用枚舉2?n2-\sqrt{n}2?n?就行,因為如果不是素數,那么必存在n=abn=abn=ab,用反證法可以證明必有一個數小于n\sqrt{n}n?;

代碼

bool is_prime(int n) {if(x<=1)return false;for(int i=2;i*i<=n;i++){if(x%i!=0)return true;}return false; }

多個素數判定

假如給你1-n,n個數,讓你判斷這n個數是不是素數,如果按照上述算法每個判斷的話,復雜度為O(nn)O(n\sqrt{n})O(nn?),下邊引入一種篩法,可以將復雜度降為O(nlogn)O(nlogn)O(nlogn).

篩法:
一個非素數,肯定可以被它的約數整數,那枚舉約數把約束的倍數標記,未被標記的數就是質數

代碼

void is_primes(int n) {for(int i=2;i<=n;i++){ for(int j=i;j<=n/i;j++){ v[i*j]=1;}}} //復雜度計算:n(1+1/2+1/3+……)調和級數

代碼優化-埃氏篩

剛剛那個會有很多重復標記,比如24,在i=2(212)的時候標記一次,在i=4(46)的時候標記一次
這次優化減少了部分重復計算
從質數的倍數都為合數的角度(剛剛是1-n所有數的倍數,由唯一分解定理可知,合數一定可以分解為素數的乘積),每次只標記素數的倍數,因為合數的話一定可以寫為素數相乘的形式,在素數時被標記過一次,如果合數再標記一次就會重復。

void is_primes(int n) {for(int i=2;i<=n;i++){ //是不是素數,初始化均為素數0if(v[i]) continue;//是素數的話就開始標記for(int j=i;j<=n/i;j++){ v[i*j]=1;}}} //復雜度:O(nloglogn)

歐拉篩(繼續優化)

上邊的方法還是會有重復,比如12,在i=4(3)、6(2)的時候都會被標記一次,所以可以每次用一個數最小的質因子去篩掉合數(用素數去篩合數)且只用最小質因子去一次就行(比如12,只用素數2篩一次也就是只在62的時候再篩(更大的倍數i乘以更小的素數計算出12),所以要達到內層循環在乘完42就break的效果)

void is_primes(int n) {for(int i=2;i<=n;i++){ if(!v[i]) primes[++cnt]=i; //,初始化為0代表全是素數,i是素數for(int j=1;j<=cnt&&i*primes[j]<=n;j++){ v[i*primes[j]]=1; //所有質數的i倍,從最小倍開始,防止重復if(i%primes[j]==0)break;//如果i是prime的倍數的話//每個合數只被它的最小質因子篩一次//比如:12當i=12;prime=2(指的是prime是最小質因子而不是外層循環,外層循環代表的是倍數)的時候24才會被篩掉,所以i=8時對應prime=3會break掉(也就是i=8除以2為整數的時候)// 整體的來講,i是prime[j]的倍數時,i = kprime[j],若不break繼續算 i乘以下一個,則i * prime[j+1] = prime[j] * k prime[j+1],這里prime[j]是最小的質因子,也就是算了兩次,當i = k * prime[j+1]時會多重復了一次,所以才跳出循環。}}} //復雜度:O(n)

牛牛與LCM

(C++庫中自帶求最大公因子函數,可以直接拿來用)

#include<bits/stdc++.h> using namespace std; //若干個數,不是兩個數 int lcm(int a,int b) {return a*b/__gcd(a,b); } int main() {int n;cin>>n;int *a=(int *)malloc(sizeof(int)*n);for(int i=0;i<n;i++){cin>>a[i];}int x;cin>>x; //這里要開long longlong long ans=1;for(int i=0;i<n;i++){//x是a[i]的倍數//不僅要是倍數還要是最小公倍數if(x%a[i]==0){ans=lcm(ans,a[i]);}}if(ans==x){cout<<"Possible";}elsecout<<"Impossible";return 0; }

Sum of Consecutive Prime Numbers


這個題涉及兩個知識點,求1~n的素數有哪些,上邊已經講解過歐拉可以達到線性復雜度;另一個點就是在一串從小到大的數組中,找到和為x的一段,起初看到的時候,基于現有的知識,首先想到的是前綴和,也就是說:先求出前綴和序列,然后借助兩個指針表示所選取的序列,指針所指兩個前綴和序列對應數做減法得到指針之間這段序列的和,通過移動指針來得到最終結果(指針的初始位置均指向第一個數,若所指段和小于x,則右指針右移,若大于則左指針右移)。
但是看完題解,學到了基于滑動窗口的方法做這個題,整體思路一樣,借助兩個指針,通過移動來找到最終結果,初始sum值即為第一個數,當右指針右移時sum加當左指針右移時sum減,sum與x比較,同樣可以得到最終結果,并且省去了一個做前綴和的過程。

//題目給出了n的上限,且如果每次只按照當前n值找素數的話,會比較麻煩,所以直接一次性計算到上限 #include<bits/stdc++.h> using namespace std;int main() {//復習下,先不要看之前的筆記,需要維護一個素數數組和結果數組int prime[int(4e7)+1];bool is[int(4e7)+1];//開兩個int,空間會超,改成boolint cnt=0;memset(prime,0,sizeof(int)*(int(4e7)+1));memset(is,0,sizeof(bool)*(int(4e7)+1));for(int i=2;i<=int(4e7);i++){if(!is[i])prime[++cnt]=i;for(int j=1;j<=cnt&&i*prime[j]<=int(4e7);j++){is[i*prime[j]]=1;if(i%prime[j]==0)break;}}int T;cin>>T;int flag=1;while(flag<=T){flag++;int n;cin>>n;int l=1;int r=1;int ans=0;int sum=prime[1];for(;l>=1 && r<=cnt&&l<=r;){if(sum>=n){if(sum==n)ans++;sum-=prime[l];l++; }else if(sum<n){//這里順序不要反了啊r++;sum+=prime[r];}}cout<<ans<<endl; }return 0; }

Prime Distance(區間篩)


在素數判定中有提到,只用循環至n\sqrt nn?,那么同理,一個數n的最小質因子一定小于等于n\sqrt nn?(同樣反證法),也就是說,我們僅需要知道2~n\sqrt nn?的素數,就可以篩選1~n

這個題一定要記得long long!!

//這個題目和上個題目不一樣之處在于,開不出來2的31次方的數組,并且篩到2的31次方的話即使是線性復雜度也會超時 //所以要做區間篩 #include <bits/stdc++.h> using namespace std; const int N=1e6+10; //只篩選出該范圍內的素數就行 const int range=46341+10; int prime[range]; bool is[range]; int p[N]; int max(long long a,long long b) {return a>b?a:b; } int main() {int cnt=0;memset(is,0,sizeof(int)*(range));for(int i=2;i<=range-10;i++){if(!is[i])prime[++cnt]=i;for(int j=1;j<=cnt&&i*prime[j]<=range-10;j++){is[i*prime[j]]=1;if(i%prime[j]==0)break;}}int T;cin>>T;long long r;long long l;while(T--){memset(p,0,sizeof(int)*(N));cin>>l>>r;//篩區間的時候用埃氏篩,歐拉篩會超時//因為直接按照倍數標記就行了,歐拉的話還要循環至質因數最小的那個倍數/*for(int i=max(2,l/prime[cnt]);i<=r/2+1;i++){for(int j=1;j<=cnt&&i*prime[j]>=l&&i*prime[j]<=r;j++){p[i*prime[j]-l]=1;if(i%prime[j]==0)break;}}*/for (long long i = 1; i <= cnt && prime[i] <= r; i++) {long long w = (l + prime[i] - 1) / prime[i];//第一個數是i的多少倍for (long long j = max(2, w); prime[i] * j <= r; j++)p[prime[i] * j - l] = 1;}vector<long long int > pri;for (long long i = max(2, l); i <= r; i++) { if (!p[i - l]) pri.push_back(i);p[i - l] = 0;}/*for(int i=0;i<N;i++){if(i+l>r)break;if(p[i]==0)pri.push_back(i);}*/if(pri.size()<=1){cout<<"There are no adjacent primes."<<endl;continue;}else{pair<long long,long long> min={0x3f3f3f3f3f,-1},max={-1,-1};for(long long i=0;i<pri.size()-1;i++){if(pri[i+1]-pri[i]>max.first){max.first=pri[i+1]-pri[i];max.second=i;}if(pri[i+1]-pri[i]<min.first){min.first=pri[i+1]-pri[i];min.second=i; }}cout<<pri[min.second]<<','<<pri[min.second+1]<<" are closest, "<<pri[max.second]<<','<<pri[max.second+1]<<" are most distant."<<endl;continue;}}return 0; }

實現唯一分解定理

就是從最小的素數開始一個一個除

for(int i=1;i<=cnt&&i<sqrt(n);i++) {while(n%prime[i]==0){a[c++]=prime[i];n=n%prime[i];} }

X-factor Chains


題中要求序列盡可能地長,也就是所有ai+1=t?aia_{i+1}=t*a_iai+1?=t?ai?中的t都要盡量的小,換個思路,質數是不能再分的,也就是說如果4*a可以寫作2?2?a2*2*a2?2?a從而達到t最小的效果,所以這道題就是實現唯一分解定理,然后對素數計算全排列

總結

以上是生活随笔為你收集整理的数论基础入门的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 欧美精品一区二区三区三州 | 国产精品一区二区免费在线观看 | 在线看视频 | 欧美bdsm调教视频 | 黄色片网站国产 | 亚洲色图国产精品 | 最新欧美日韩 | 亚洲乱熟 | 三级黄在线观看 | 久久人人爽爽人人爽人人片av | 97超碰人 | 亚洲国产欧美在线观看 | 国产精品视频成人 | 黄色大片aa | 综合久久久久 | a视频在线免费观看 | 97热视频| 波多一区 | 日韩综合 | 日本www视频| 性欧美丰满熟妇xxxx性久久久 | 成人黄色一级视频 | 日韩一区二区三区在线 | 久久合| 先锋影音制服丝袜 | 亚洲大胆人体 | 三级黄色短视频 | 天天干天天舔天天操 | 国产成人精品综合久久久久99 | 国产粉嫩呻吟一区二区三区 | 激情五月深爱五月 | 中文字幕一二三四区 | 秘密爱大尺度做爰呻吟 | 午夜免费观看 | 久草视频免费在线播放 | 亚洲伦理在线 | 自拍偷拍第1页 | 欧美乱欲视频 | 黑人玩弄人妻一区二区三区影院 | 超碰在线人人草 | 91av手机在线 | 欧美日韩一级在线观看 | 亚洲国产视频在线观看 | 射射射综合网 | 欧美激情自拍 | 解开乳罩喂领导吃奶 | 亚洲精品小说 | 97人人模人人爽人人少妇 | av日韩一区二区 | 欧美不卡在线视频 | 特级西西444www高清大视频 | 一级女人毛片 | 操欧美老女人 | 精品久久一区 | 欧美色综合网站 | 国产成人自拍偷拍 | 国产精品jizz在线观看软件 | 中文字幕精品三级久久久 | 男女av网站 | 国产精品久久影视 | 一本到高清 | 99热在线观看免费精品 | 国产裸体网站 | 免费特级黄毛片 | 欧美婷婷六月丁香综合色 | av国产成人 | 国产中文字幕第一页 | 91片黄在线观看喷潮 | 日韩av成人在线观看 | 91久久国产视频 | 美女毛毛片 | 亚洲AV无码阿娇国产精品 | 国产全是老熟女太爽了 | 国产suv精品一区二区6 | 色哟哟官网 | 91精品综合久久 | 中文字幕二区 | 亚洲av永久无码精品一区二区国产 | www成年人| 欧美日韩毛片 | 国产精品视频网址 | 日本一二三视频 | 国产美女av| 国产精品高清在线 | free欧美性69护士呻吟 | 色欲一区二区三区精品a片 在线观看黄网站 | 名人明星三级videos | av福利在线看 | 亚洲另类色综合网站 | 色婷婷欧美 | 福利视频免费看 | 亚洲色图日韩 | 日韩久久不卡 | 天堂av免费在线 | 鸭子av| 五月婷丁香| 嫩草在线观看 | 男生草女生视频 | 成人免费看片视频 |