初等数论c++.docx
- 文档编号:10076554
- 上传时间:2023-02-08
- 格式:DOCX
- 页数:15
- 大小:20.58KB
初等数论c++.docx
《初等数论c++.docx》由会员分享,可在线阅读,更多相关《初等数论c++.docx(15页珍藏版)》请在冰豆网上搜索。
初等数论c++
备注:
纯手写代码,注释。
数论
1、素数
(1)暴力求解法
ﻩ根据素数得概念,没有1与其本身没有其她正因数得数。
所以只需枚举比这个数小得数,瞧能整除即可;
C++代码:
#include<iostream〉
#include〈cstdio〉
#include<cmath>
using namespace std;
booldetermine(intnumber)
{
if(n<=2)returnfalse;
if(!
n%2)returnfalse;
for(inti=3;i<=ceil(sqrt(number));i+=2)
//去掉了偶数得判断,效率提高一倍
ﻩ/*如果number整除以i,那么会得到两个得因数,
而较小得那个因数不会超过number得二分之一次方;
所以只需判断到number得平方根向上取整即可;*/
ﻩﻩif(number%i);
elsereturnfalse;
ﻩreturntrue;
}
intmain()
{
ﻩintsum;
cin>〉sum;
if(determine(sum))
ﻩcout<〈"YES!
”;
ﻩelsecout<<"NO!
”;
ﻩreturn0;
}
时间复杂度:
o(sqrt(n)/2);
空间复杂度:
几乎没有;
(2)一般线性筛法:
ﻩ因为任何一个合数都能分解成几个素数相乘得形式;
所以可以做一个表,首先把2设为质数,然后将2得倍数设为合数,剩下得数就就是新得到得质数,然后重复这个过程,直到筛到合适得范围即可;
但就是这个算法有缺陷:
1、同一个数可能被筛多次,这就产生了多余得步骤。
2、占用空间很大,如果使用bool数组得话,只能筛到1e9;
3、从1—n筛,不能从m-n开始筛;
C++代码:
#include<cstring〉
#include #include<iostream〉 usingnamespace std; bools[1000000000]; intm,n; intmain() { ﻩcin>>m>>n; memset(s,true,n); ﻩs[0]=s[1]=0; ﻩ//输出M—N之间所有素数; ﻩfor(int i=2;i<=ceil(sqrt(n));++i) ﻩif(s[i]) { ﻩﻩﻩfor(int j=i;j〈=n;++j) ﻩﻩif(s[i*j]) ﻩﻩs[i*j]=false; ﻩ} for(int i=m;i〈=n;++i) ﻩif(s[i]) cout< return0; } 时间复杂度: o(n*loglogn); 空间复杂度: 很大! 注意数据大得话可能会爆空间; (3)线性筛法求素数 这个占空间就更大了,需要使用一个bool数组与int数组 而亲身试验得到int数组最多开到1e8…… 很无语,快确实就是快了,但就是测试数据一大,爆空间就更容易了; #include〈iostream> #include〈cstdio〉 #include〈cmath> usingnamespace std; intm,n,sum; bool inp[1000000000]; ints[100000000]={0,0}; intmain() { ﻩcin>〉m>〉n; ﻩfor(inti=2;i<=n;++i) ﻩ{ ﻩif(! inp[i]) ﻩs[sum++]=i; for(intj=0;j ﻩ{ ﻩinp[i*s[j]]=true; ﻩif(! (i*s[j])) ﻩﻩbreak; ﻩ} ﻩ} ﻩfor(inti=m;i<=n;++i) ﻩif(! inp[i]) cout< return0; } 2、唯一分解定理 任何数都可以被唯一得分解成多个素数之积 例如: 456=2*2*2*3*19; C++代码: #include #include #include #include〈algorithm> #include〈cstdlib> using namespacestd; bool s[1000000]; int m,n,sum=0,num; int Prime[1212121]; intzhi[1500]; voidPrimes() { ﻩfor(inti=1;i〈=num;++i) ﻩs[i]=true; ﻩs[0]=s[1]=0; for(inti=2;i<=num;++i) ﻩﻩif(s[i]) ﻩ{ Prime[++sum]=i; ﻩﻩﻩfor(intj=i;j<=num;++j) ﻩif(s[i*j]) ﻩﻩﻩs[i*j]=false; ﻩ} } intmain() { ﻩintflag=0; ﻩcin>〉num; intnumber=num; Primes(); if(s[num]) ﻩ{ cout<〈num<〈'='〈〈num; ﻩﻩreturn0; ﻩ} cout〈<num<<"=”;str.chu(); while(num>1) ﻩfor(inti=1;num〉1&&i<=sum;++i) ﻩif(! (num%Prime[i])) ﻩ{ ﻩﻩzhi[++flag]=Prime[i]; ﻩnum/=Prime[i]; ﻩﻩ} sort(zhi+1,zhi+flag+1); cout〈<zhi[1]; ﻩfor(inti=2;i〈=flag;++i) cout<〈"*"<〈zhi[i]; return0; } 首先做一个质数表,并把质数存到数组里,然后用数模每个素数,如果为0则记录素数,最后排个序输出; 4、欧拉函数 欧拉函数φ(n)为不大于n得与n互素得数得个数; A与B互素,表示a与b得最大公约数为1,即(a,b)=1; 欧拉函数得符号φ读作fhi,在搜狗得特殊符号里可以找到; 其中pi为x得质因数,其中φ (1)=1(唯一与1互质得数就是1本身) 设n为正整数,以φ(n)表示不超过n且与n互素得正整数得个数,称为n得欧拉函数值 φ: N→N,n→φ(n)称为欧拉函数。 几个性质(来自XX百科) 1、若n就是质数p得k次幂, ,因为除了p得倍数外,其她数都跟n互质。 2、欧拉函数就是积性函数--若m,n互质, 3、特殊性质: 当n为奇数时, ,证明与上述类似。 4、若n为质数则 5、设p就是素数,a就是一个正整数,那么 C++实现: #include<cstring〉 #include<cmath〉 #include<iostream> #include<algorithm〉 #include〈cstdlib〉 usingnamespacestd; bools[1000000]; intm,n,sum=0,num; int Prime[1212121]; int zhi[1500]; boolasd[1500]; intphi(intn) { int i,rea=n; for(i=2;i*i<=n;i++) { if(n%i==0) { rea=rea-rea/i; while(n%i==0) n/=i; } } if(n〉1) rea=rea-rea/n; returnrea; } voidPrimes() { for(inti=1;i<=num;++i) ﻩﻩs[i]=true; ﻩs[0]=s[1]=0; ﻩfor(inti=2;i<=num;++i) ﻩif(s[i]) ﻩ{ Prime[++sum]=i; ﻩﻩfor(intj=i;j〈=num;++j) if(s[i*j]) ﻩﻩﻩs[i*j]=false; ﻩ} } int main() { intflag=0; cin>>num; ﻩintnumber=num; Primes(); if(num==1||! num) ﻩ{ ﻩcout〈〈"fhi"〈<’(’〈 ﻩﻩcout〈〈num; ﻩﻩreturn0; } ﻩif(s[num]) { cout<〈"fhi”〈<'(’< ﻩreturn 0; ﻩ} while(num>1) ﻩfor(inti=1;num〉1&&i〈=sum;++i) ﻩif(! (num%Prime[i])) { ﻩﻩﻩzhi[++flag]=Prime[i]; ﻩnum/=Prime[i]; } ﻩintfenzi=1,fenmu=1; sort(zhi+1,zhi+flag+1); ﻩfor(inti=1;i〈=flag;++i) if(! asd[zhi[i]]) ﻩﻩ{ ﻩasd[zhi[i]]=true; fenzi*=zhi[i]-1; ﻩfenmu*=zhi[i]; ﻩ} cout<〈"fhi(”< //cout<〈"fhi("< /*这就是另一种求欧拉函数值得方法*/ return0; } 5、欧几里得算法 辗转相除法,根据公式(a,b)=(b,r) 其中r为a%b,即a/b; C++代码: (1)递归 #include #include<cstdio> usingnamespacestd; intGCD(inta,int b) { ﻩif(a%b) ﻩ return GCD(b,a%b); ﻩelse returnb; } intmain() { inta,b; ﻩcin>>a>〉b; cout〈〈GCD(a,b); return0; } (2)递推 #include<iostream> using namespace std; intmain() { ﻩinta,b,r; ﻩcin〉>a〉>b; ﻩr=m%n; while(r! =0) ﻩ{ a=b; ﻩb=r; ﻩr=m%n; ﻩ} ﻩcout< ﻩreturn 0; } 6、扩展欧几里得 扩展欧几里得又称斐蜀定理,对于不完全为0得非负整数a,b,gcd(a,b)表示a,b得最大公约数,必然存在整数对x,y,使得gcd(a,b)=ax+by; 求同余方程 #include voidexgcb(inta,int b,int&x,int&y) { ﻩif(! b) ﻩ{ ﻩx=1;y=0; return; } intq=a/b; ﻩintr=a%b; exgcb(b,r,y,x); y-=q*x; } intmain() { intx,y; inta,b; scanf(”%d %d",&a,&b); ﻩexgcb(a,b,x,y); while(x〈0) ﻩx+=b; ﻩprintf("%d",x); return0; } 求乘法逆元 #include〈cstdio> void exgcb(int a,int b,int&x,int &y) { if(! b) { ﻩx=1;y=0; ﻩreturn; } intq=a/b; int r=a%b; exgcb(b,r,y,x); y—=q*x; } int Multiplicativeinverse(inta,intb) { int x,y; ﻩint gcb=GCD(a,b,x,y); if(1%gcb)return-1; x*=1%gcb; ﻩb=abs(b); ﻩintanswer=x%b; while(answer<=0) ﻩﻩanswer+=b; return answer; } intmain() { ﻩintx,y; ﻩinta,b; ﻩscanf(”%d %d",&a,&b); ﻩexgcb(a,b,x,y); while(x<0) ﻩx+=b; ﻩprintf(”%d\n",x); cout<<Multiplicative inverse(a,b); ﻩreturn0; } 求线性方程ax+by=c 这个方程等同于ax≡c(modb) 所以
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 初等 数论 c+