1. 程式人生 > >數論部分知識

數論部分知識

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;
 4
int 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 }

數論部分知識