常用的數論演算法(C++描述)
阿新 • • 發佈:2019-02-03
網上找到的是PASCAL的……於是自己轉成C++來寫一遍……
1.求兩數的最小公倍數和最大公約數
//(輾轉相除法/歐幾里德演算法)//求兩數的最大公約數
int gcd(int a,int b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
//擴充套件:求出gcd(a,b)和滿足gcd(a,b)=ax+by的整數x和y
//理論依據:gcd(a,b)=ax+by=bx1+(a mod b)y1=bx1+(a-(a div b)*b)y1=ay1+b(x1-(a div b)*y1))
int exgcd(int a,int b,
{
int t;
if(b==0)
{
x=1;
y=0;
return a;
}
t=x;
x=y;
y=t-a/b*y;
return exgcd(b,a%b,x,y);
}
//求兩數的最小公倍數
//(根據最大公約數直接計算)
int lcm(int a,int b)
{
return a*b/gcd(a,b);
}
//(直接計算)
int lcm2(int a,int b)
{
if(b>a) {int t=a;a=b;b=t;}
int l=a;
l+=a;
return l;
}
使用方法:最大公約數x=gcd(a,b);最小公倍數y=lcm(a,b)或lcm2(a,b),當要求gcd(a,b)=ax+by時最大公約數=exgcd(a,b,&x,&y),x=x,y=y(順序不可調換)。
2.判斷一個數是否是素數
// 小範圍內求素數bool ifprime(int n)
{
for(int i=2;i<=int(sqrt(double(n)));i++)
if(n%i==0)
returnfalse;
returntrue;
// unsigned long範圍內求素數(包含求50000的素數表)
constint N=50000;
bool prime[N];
int pr[N],l;
void getprime()
{
int i,j;
for(i=1;i<N;i++)
prime[i]=true;
prime[0]=false;
i=1;
while(i<N)
{
if(prime[i])
{
j=(i+1)*2;
while(j<N)
{
prime[j-1]=false;
j+=i+1;
}
}
i++;
}
l=0;
for(i=1;i<N;i++)
if(prime[i-1])
{
l++;
pr[l]=i;
}
}
bool isprime(unsigned long x)
{
for(int i=1;i<l;i++)
if(pr[i]>=x)
break;
else
if(x%pr[i]==0)
returnfalse;
returntrue;
}
使用方法:小範圍內素數直接判斷ifprime(n)即可,long型先呼叫getprime()生成素數表,再分別判斷isprime(n)。
3.分解素數因子
vector <pair <int, int>> primeFactor(int n)...{
vector < pair <int, int>> v;
for(int i=1; primes[i] * primes[i] <= n; i++ ) ...{
int k =0 ;
while ( n %primes[i] ==0 ) ...{
k ++ ;
n/=primes[i] ;
}
if ( k )
v.push_back(make_pair( primes[i], k));
}
if (n !=1)
v.push_back (pair <int, int> (n, 1));
return v;
}
上面的程式我沒有執行過。可是,如果只是得出形如這樣的結果,我以為下面的程式就可以執行勒 = = .. #include<stdio.h>
int main()
{
int x,i;
scanf("%d",&x);
printf("%d=",x);
if(x<0) { x*=-1;printf("-");}
while(1)
{
for(i=2;i<x;)
{
if(x%i==0)
{
printf("%d*",i);
x/=i;
if(x==0) break;
}
else i++;
}
printf("%d ",x);
break;
}
return0;
}
因為如果不是素數的話它的因子不是早就被前面的素數除光了麼 = = ...
4.求N以內的素數個數
long A[n+1];void countprime(unsigned long n)
{
long i,temp;
A[1]=0;
for(i=2;i<=n;i++)
A[i]=1;
for(i=2;i<=int(sqrt((double)n));i++)
{
if(A[i])
{
temp=i*i;
while(temp<=n)
{
A[temp]=0;
temp+=i;
}
}
}
}
void count(unsigned long n)
{
unsigned long i;
countprime(n);
for(i=2;i<=n;i++)
A[i]+=A[i-1];
}
使用方法:呼叫count(n)即可得出,不過記得要先開一個足夠大的全域性陣列A。
5.十進位制轉換為其他進位制
void Ten(long x,int d){
int i,n=0,h=1;
int s[32]=