初等数论c++.docx

上传人:b****8 文档编号:10076554 上传时间:2023-02-08 格式:DOCX 页数:15 大小:20.58KB
下载 相关 举报
初等数论c++.docx_第1页
第1页 / 共15页
初等数论c++.docx_第2页
第2页 / 共15页
初等数论c++.docx_第3页
第3页 / 共15页
初等数论c++.docx_第4页
第4页 / 共15页
初等数论c++.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

初等数论c++.docx

《初等数论c++.docx》由会员分享,可在线阅读,更多相关《初等数论c++.docx(15页珍藏版)》请在冰豆网上搜索。

初等数论c++.docx

初等数论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)

所以

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1