数论部分知识
Posted wxyww
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论部分知识相关的知识,希望对你有一定的参考价值。
费马定理:
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 }
以上是关于数论部分知识的主要内容,如果未能解决你的问题,请参考以下文章