欧几里得算法(辗转相除法)
用途:用于求两个数的最大公因数
基础:如果c为a和b的最大公因数,那么c也一定为b和a%b的最大公因数,同理,c也为a%b和b%(a%b)的最大公因数,其中b等于0时最大公因数c等于a
#include <stdio.h>
int max_div(int a,int b){
return (b? max_div(b,a%b) : a);
}
int main(){
printf("%d\n", max_div(15,10));
return 0;
}
素数筛
用途:求一定范围内的素数
基础:如果a为素数,那么ak(k=2,3,4…)一定为和数,于是可以定义一个数组,将和数ak都进行标记,剩下的未标记的都为素数
#include <stdio.h>
void prime(int flage[], int n){
for(int i=2; i<n; ++i){
if(flage[i]) continue;
for(int j=i; j<n-i; j+=i){
flage[i+j]=1;
}
}
}
int main(){
int flage[101]={0}; //因为我们要数字1和索引1相对应,所以多定义一个元素
prime(flage,101);
for(int i=2; i<101; ++i){
if(flage[i]) continue;
printf("%d\n", i);
}
return 0;
}
考虑到最终还要判断该数字是否为素数,不如一开始就将素数记录下来
因为素数个数的增长慢于对数字的列举,于是可以利用原来的数组记录素数
#include <stdio.h>
void prime(int flage[], int n){
for(int i=2; i<n; ++i){
if(flage[i]) continue;
flage[ ++flage[0] ]=i;//用flage[0]记录素数的个数,用i已经利用过的元素记录素数值
for(int j=i; j<n-i; j+=i){
flage[i+j]=1;
}
}
}
int main(){
int flage[101]={0}; //因为我们要数字1和索引1相对应,所以多定义一个元素
prime(flage,101);
for(int i=1; i<=flage[0]; ++i){
printf("%d\n", flage[i]);
}
return 0;
}
线性筛
用途:求一定范围内的素数
基础:一个和数一定可以写成一个最小素因子乘以一个最大因子的形式(最小素因子一定是小于等于最大因子的,并且最大因子分解产生的所有素因子一定是大于等于这个最小素因子的),可以选定一个最大因子,列举最小素因子,则它们的乘积一定为合数,定义一个数组,标记掉这些和数
#include <stdio.h>
void prime(int flage[], int n){
for(int i=2; i<n; ++i){
if(!flage[i]) flage[ ++flage[0] ]=i;
for(int j=1; j<flage[0]; ++j){
if(i * flage[j] >= n) break;
flage[i * flage[j]]=1;
if(i % flage[j] == 0) break;
}
}
}
int main(){
int flage[101]={0}; //因为我们要数字1和索引1相对应,所以多定义一个元素
prime(flage,101);
for(int i=2; i<101; ++i){
if(flage[i]) continue;
printf("%d\n", i);
}
return 0;
}
二分查找
用途:快速在一个有序区间内查找指定值
基础:在将有序区间分为两个部分,如果指定值大于中点的值则指定值在右区间,如果小于中点的值则指定值在左区间,然后再把相关区间分为两部分继续上述操作
#include <stdio.h>
#define EXP 1e-6
double f(double x){
return x*x;
}
double sqrt(double x){ //二分查找实现sqrt函数
double left=0,right7=(x<1)? 1: x;//当x小于1时,令right等于x会使得所求解在区间之外
while(right-left < EXP){
double mid=(left+right)/2;
if(f(mid) > x){
right=mid;
}else if(f(mid) < x){
left=mid;
}else{
return mid;
}
}
return left;
}
int main(){
printf("%g/n",sqrt(0.23));
return 0;
}
牛顿迭代法
用途:求方程的根
基础:用切线逼近方程的解,由f(x0)-0 = f1(x0)(x0-x)得到x = x0 - f(x0)/f1(x0),逐步用x逼近方程y = xx - c,y=0时的解,其中f(x)为原函数,f1(x)为导函数
#include <stdio.h>
#include <math.h>
double f(double x, double c){//原函数
return x*x - c;
}
double F(double x){ //导函数
return 2*x;
}
double newton(double (*f)(double, double),double (*F)(double), double c){
double x = b; //方程的一个解在0-b之间
#define EXP 1e-6
while(fabs( f(x,c) ) > EXP){
x -= f(x,c) / F(x);
}
#undef EXP
return x;
}
int main(){
printf("%g/n", newton(f,F,0.23)); //0.23开根号
return 0;
}