常见数学问题

最大公约数:辗转相除法, 0和a的最大公因子为a;

int gcd(int a, int b){
    if(b==0) return a;
    return gcd(b, a%b);
}
int gcd(int a, int b){
    return !b ? a : gcd(b, a%b);
}

a和b的最小公倍数: 设a,b的最大公因子为d, 则最小公倍数为ab/d, 但是ab可能会导致溢出,应该先算除法再算乘法,即最小公倍数为a/d*b

1 int gcd(int a, int b){
2     return !b ? a : gcd(b, a%b);
3 }
4 
5 int lcm(int a, int b){
6     return a/gcd(a, b)*b;
7 }

分数运算:

用结构体保存分子,分母;为了避免乘法溢出, 分子分母用long long 保存, 满足以下条件

1.让分母非负数

2.如果分母为0, 规定分子为1

3.分子,分母互质

分数的化简:

1.如果分母为负, 分母取绝对值, 分子取相反值

2.求出分子分母绝对值的gcd,然后约分

分数除法:用除法前,先判断除数的分母是否为0, 如果是就不要调用除法函数啦

分数的输出:一般有这样的要求:

1.如果分子大于分母 以带分数的形式输出

2.如果分子除以分母为整数,就不输出分母;

3.真分数输出最简形式

 1 struct Fraction{long long up, down;};
 2 
 3 Fraction reduction(Fraction result){
 4     if(result.down<0){
 5         result.down = -result.down;
 6         result.up = -result.up;
 7     }else if(result.up==0) result.down=1;
 8     else{
 9         int d=gcd(abs(result.up), abs(result.down));
10         result.up /= d;
11         result.down /= d;
12     }
13     return result;
14 }
15 
16 Fraction add(Fraction a, Fraction b){
17     Fraction result;
18     result.up = a.up*b.down + b.up*a.down;
19     result.down = a.down*b.down;
20     return reduction(result);
21 }
22 
23 Fraction minu(Fraction a, Fraction b){
24     Fraction result;
25     result.up = a.up*b.down - b.up*a.down;
26     result.down = a.down*b.down;
27     return reduction(result);
28 }
29 
30 Fraction multi(Fraction a, Fraction b){
31     Fraction result;
32     result.up = a.up*b.up;
33     result.down = a.down*b.down;
34     return reduction(result);
35 }
36 
37 Fraction divid(Fraction a, Fraction b){
38     Fraction result;
39     result.up = a.up*b.down;
40     result.down = a.down*b.up;
41     return reduction(result);
42 }
43 
44 void output(Fraction a){
45     a = reduction(a);
46     if(a.down==1) printf("%d\n", a);
47     else if(abs(a.up)>abs(a.down)) printf("%d %d/%d\n", a.up/a.down, a.up%a.down, a.down);
48     else printf("%d/%d\n", a.up, a.down);
49 }

素数判断:循环次数最好不要用i*i<=n 来进行, 因为当i比较大的时候,可能溢出;  复杂度为O(N^1.5)) ; 在10^5范围内这个复杂度是可以接受的

1 bool isPrime(int n){
2     if(n<2) return false;
3     int cnt = (int) sqrt(1.0*n);
4     for(int i=2; i<=cnt; i++)
5         if(n%i==0) return false;
6     return true;
7 }

高效的求解素数的方法:筛选法 复杂度为nloglogn

能求出1~maxn之间的素数个数, 素数,以及是否是素数; 

 1 const int maxn = 101;
 2 int prime[maxn],  vis[maxn]={0};
 3 int getPrime(){
 4     int pNum=0;
 5     for(int i=2; i<maxn; i++){
 6         if(!vis[i]){
 7             prime[pNum++]=i; 9             
        for(int j=i+i; j<maxn; j += i) vis[j] = 1; 11 } 12 } 13 return pNum; 14 }

2*3*5*7*11*13*17*19*23*19的结果已经超出int的范围,所以要求解某个数字的素数因子的时候,只需要一个大小为10的数组来保存就行了;

例题:https://www.cnblogs.com/mr-stn/p/9225971.html

猜你喜欢

转载自www.cnblogs.com/mr-stn/p/9225649.html
今日推荐