1. 程式人生 > >常用的數論演算法(C++描述)

常用的數論演算法(C++描述)

網上找到的是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&x,int&y)
{
   
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;
    
while(l%b)
        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 <intint>> primeFactor(int n)
...
{
        vector 
< pair <intint>> 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 
<intint> (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==0break;
     }

     
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]=