數論部分知識
阿新 • • 發佈:2018-05-03
can ron phi print con code 個數 nbsp turn
費馬定理:
ap≡a(mod p)
其中p為質數,且a不是p的倍數
證明:
。。。。。
歐拉定理:
aφ(p)≡1(mod p)
φ(x)(歐拉函數)為小於等於x且與x互質的數的個數
φ(x)=∏(pi-1)*piki-1 其中pi表示 x的質因數,ki表示這種質因數的個數
特別的對於質數 φ(x)=x-1。
歐拉函數的代碼實現:
1 #include<cstdio> 2 #include<Iostream> 3 using namespace std; 4int ol(int x) 5 { 6 int ans=1; 7 for(int i=2;i*i<=x;++i) 8 { 9 if(x%i==0) 10 { 11 x/=i; 12 ans*=i-1; 13 } 14 while(x%i==0) 15 { 16 x/=i; 17 ans*=i; 18 } 19 } 20 if(x>1) ans*=x-1; 21 return ans; 22 } 23 int main() 24 { 25 int a; 26 scanf("%d",&a); 27 printf("%d",ol(a)); 28 return 0; 29 }
最後函數裏那個如果x>1,ans*=x-1一開始讓我很懵,後來一想,如果這個數將所有的質因數除過一遍之後,剩下的數如果不是1,那麽剩下的肯定只有一個並且是個質數(證明很顯然)
篩法
有兩種篩法,第一種叫做埃拉托斯特尼篩法(復雜度O(n log logn)),另一種是歐拉篩法(復雜度O(n))
埃拉托斯特尼篩法其實就是用已得到質數,去將他的所有n以內倍數標記為合數,最後剩下的就是合數。
在進行篩法的同時,可以順便找到每個數的最小質因數(就是第一次更新他的那個質數)
歐拉篩法:在埃氏篩法中每一個合數可能會被更新很多遍,這些是沒有必要的,所以就有了歐拉篩。
歐拉篩的思路就是保證每個合數只被他的最小質因數篩掉。用一個數組dis來存已經得到的素數,
然後再用已經得到素數取篩其他的數,主要的地方是代碼中 if(i%dis[j]==0) break; 這個地方。
兩個篩法的代碼
1 #include<cstdio> 2 #include<iostream> 3 4 using namespace std; 5 const int N=10000; 6 void aa(int n); 7 void ol(int n); 8 int main() 9 { 10 int n; 11 scanf("%d",&n); 12 aa(n); 13 printf("\n"); 14 ol(n); 15 } 16 17 void aa(int n)//埃氏篩法 18 { 19 int vis[N]; 20 int dis[N];//用來存最小質因數 21 for(int i=2;i<=n;++i) 22 { 23 if(!vis[i]) 24 { 25 for(int j=i*2;j<=n;j+=i) 26 { 27 if(!vis[j]) 28 { 29 vis[j]=1; 30 dis[j]=i; 31 } 32 } 33 } 34 } 35 for(int i=1;i<=n;++i) 36 { 37 if(!vis[i]) 38 { 39 printf("%d ",i); 40 } 41 } 42 } 43 void ol(int n) 44 { 45 int vis[N]; 46 int dis[N],js=0; 47 for(int i=2;i<=n;++i) 48 { 49 if(!vis[i]) 50 { 51 dis[++js]=i; 52 } 53 for(int j=1;dis[j]*i<=n;++j) 54 { 55 vis[i*dis[j]]=1; 56 if(i%dis[j]==0) break; 57 } 58 } 59 for(int i=1;i<=n;++i) 60 { 61 if(!vis[i]) printf("%d ",i); 62 } 63 }
快速冪與快速乘法
盡管快速冪與快速乘法好像扯不上什麽關系,但是東西不是很多,就一起整理到這裏吧
快速冪思想就是將ax看作x個a相乘,用now記錄當前答案,然後將指數每次除以2,然後將當前答案平方,如果x的2進制最後一位為1的話,就將答案乘以現在的數。快速乘法類似,只是將a*x看作x個a相加。
代碼
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int mi(int a,int x) 5 { 6 int ans=1; 7 for(int now=a;x>=1;x>>=1,now=now*now)//a表示底數,x表示次數 8 { 9 if(x&1) ans=ans*now; 10 } 11 return ans; 12 } 13 int cheng(int a,int x)//表示a*x 14 { 15 int ans=0; 16 for(int now=a;x>=1;now=now*2,x>>=1) 17 { 18 if(x&1) ans=ans+now; 19 } 20 return ans; 21 } 22 int main() 23 { 24 int a,x; 25 scanf("%d%d",&a,&x); 26 printf("快速冪 %d\n",mi(a,x)); 27 printf("快速乘法 %d\n",cheng(a,x)); 28 return 0; 29 }
數論部分知識