数论算法基础

本文介绍了数论算法的基础知识,包括最大公约数(gcd)和最小公倍数(lcm)的计算,分数的四则运算处理,以及素数的判断和素数表的获取方法,如朴素算法和线性筛法,同时涉及到质因子的分解问题。

1.gcd和lcm

最小公倍数=两数之积÷最大公约数
求最大公约数:

int gcd(int a, int b){
    return b?gcd(b, a%b):a;
}

为防止溢出,lcm(a, b)=q/gcd(a, b)*b. 即先除以最大公约数再乘以另一个数得到最小公倍数。

2.分数的四则运算

使用结构体来存放分数的分子和分母你,保证分母一定为正,符号都在分子上。当分子为0时让分母为1。

//分数运算
#include <iostream>
using namespace std;

int gcd(int a, int b){
    if(b==0) return a;
    else return gcd(b, a%b);
}
struct Fraction{
    int up, down;
};
void reduction(Fraction& result){
    if(result.down<0){
        result.up=-result.up;
        result.down=-result.down;
    } //防止分母为负
    if(result.up==0){
        //如果为0让分母变为1
        result.down=1;
    }else{
        int d=gcd(abs(result.up), abs(result.down));
        result.up/=d;
        result.down/=d;
    }
}
//四则运算:得到结果后化简分数即可
//分数输出
void showFraction(Fraction r){
    if(r.down==1) printf("%lld", r.up); //整数
    else if(abs(r.up)>abs(r.down)){
        printf("%d %d/%d", r.up/r.down, abs(r.up)%r.down, r.down);
    }else{
        printf("%d/%d", r.up, r.down);
    }
}

3.素数的判断和素数表

1.素数的判断

根据素数的定义暴力判断。

//判断n是否是素数
bool isPrime(int n){
	if(n<=1) return false;
	int sqr=(int)sqrt(1.0*n);
	for(int i=2;i<=sqr;i++){
		if(n%i==0) return false;
	}
	return true;
} 

2.素数表的获取

1.朴素?
//素数表的获取 筛选法
const int maxn=20220410; //表长
int prime[maxn], pNum=0;
bool p[maxn]={false}; //p[i]=false说明是素数 
int findPrime(){
	for(int i=2;i<maxn;i++){
		if(p[i]==false){ //是质数
		    prime[pNum++]=i;
		    for(int j=i+i;j<maxn;j+=i){
			    p[j]=true; //是合数 
		    }
	    }	
	}
	cout<<pNum<<endl;
	return pNum;
	
} 
2.线性筛
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
int primeCount=0;
int prime[1100000];
bool isPrime[11000000];
void getList(int listSize){
    memset(isPrime, true, sizeof(isPrime));
    isPrime[1]=false;
    for(int i=2;i<=listSize;i++){
        if(isPrime[i]) prime[++primeCount]=i;    
        for(int j=1;j<=primeCount&&i*prime[j]<=listSize;j++){
            isPrime[i*prime[j]]=false;
            if(i%prime[j]==0) break;
        }
    }
}

3.质因子的分解

#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;

//最大公因数
int gcd(int a, int b){
	if(b==0) return a;
	else return gcd(b, a%b);
} 
//最小公倍数
int lcm(int a, int b){
	int d=gcd(a, b);
	return (a/d)*b;
} 
//判断n是否是素数
bool isPrime(int n){
	if(n<=1) return false;
	int sqr=(int)sqrt(1.0*n);
	for(int i=2;i<=sqr;i++){
		if(n%i==0) return false;
	}
	return true;
} 
//素数表的获取 筛选法
const int maxn=20220410; //表长
int prime[maxn], pNum=0;
bool p[maxn]={false}; //p[i]=false说明是素数 
int findPrime(){
	for(int i=2;i<maxn;i++){
		if(p[i]==false){ //是质数
		    prime[pNum++]=i;
		    for(int j=i+i;j<maxn;j+=i){
			    p[j]=true; //是合数 
		    }
	    }	
	}
	cout<<pNum<<endl;
	return pNum;
	
}
 
//质因子分解
struct factor{
	int x;
	int cnt;
}fac[10];

void find_fac(int n){
	int sqr=(int)sqrt(1.0*n);
	int num=0;
	for(int i=0;i<pNum&&prime[i]<sqr;i++){
		if(n%prime[i]==0){
			//初始化一下
			fac[num].x=prime[i];
			fac[num].cnt=0;
			while(n%prime[i]==0){
				fac[num].cnt++;
				n/=prime[i];
			}
			num++;
		}
		if(n==1) break;
	}
	if(n!=1){
		fac[num].x=n;
		fac[num++].cnt=1;
	}
	//输出质因子分解结果
	for(int i=0;i<num;i++){
		if(i>0) printf("*");
		printf("%d", fac[i].x);
		if(fac[i].cnt>1) printf("^%d", fac[i].cnt);
	} 
	
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值