zoukankan      html  css  js  c++  java
  • Simple Math Problems

    最大公约数&最小公倍数

    Euclid's Algorithm:若(b eq0),那么(gcd(a,b)=gcd(b,a\%b))
    (a<b),定理会先交换a和b。
    注意:0和任意正整数a的gcd是a。

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

    时间复杂度(O(lgb)),因为每次递归问题规模都会缩减一半以上。
    最小公倍数(lcm=frac{a*b}{gcd})

    • 扩展欧几里得算法
      可以计算出满足下式的三元组((d,x,y))

    [d = GCD(a, b) = ax + by ]

    int Euclid_extend(int a, int b, int* x, int* y) {
    	if(0 == b) {
    		*x = 1;
    		*y = 0;
    		return a;
    	}
    	else {
    		int r = Euclid_extend(b,a%b,x,y);
    		int temp = *x;
    		*x = *y;
    		*y = temp - (*y)*(a/b);
    		return r;
    	}
    }
    

    简单证明:
    (b=0)是递归基,易得一组解(x=1,y=0);
    (b eq0)时:
    首先递归求解:

    [d'=gcd(b,a\%b)=bx'+(a\%b)y' (1) ]

    我们知道:

    [d=gcd(a,b)=d'=gcd(b,a\%b) (2) ]

    [a\%b=a-b*iggllfloor a/b iggr floor (3) ]

    将(2)(3)式带入(1):

    [d=bx'+(a-biggllfloor a/b iggr floor)y'=ay'+b(x'-iggllfloor a/b iggr floor y') ]

    所以,令(x=y')(y=x'-iggllfloor a/b iggr floor y'),就可以满足(d=ax+by)

    分数

    PAT甲1088是比较经典的分数处理问题,求2个分数的和、差、积、商,输出最简形式。
    表示、化简、运算、输出,代码阐释得很清楚。

    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    ll gcd(ll a,ll b)
    {
            return !b ? a : gcd(b,a % b);
    }
    
    struct Fraction{
            ll nume,deno;
    };
    
    Fraction reduction(Fraction a)
    {
            if(a.deno < 0)
            {
                    a.deno = -a.deno;
                    a.nume = -a.nume;
            }
            if(a.nume == 0)
            {
                    a.deno = 1;
            }
            else
            {
                   int d = gcd(abs(a.nume),abs(a.deno));
                   a.nume /= d;
                   a.deno /= d;
            }
            return a;
    }
    
    Fraction add(Fraction a,Fraction b)
    {
            Fraction res;
            res.deno = a.deno * b.deno;
            res.nume = a.deno * b.nume + a.nume * b.deno;
            return reduction(res);
    }
    
    Fraction sub(Fraction a,Fraction b)
    {
            Fraction res;
            res.deno = a.deno * b.deno;
            res.nume = a.nume * b.deno - a.deno * b.nume;
            return reduction(res);
    }
    
    Fraction times(Fraction a,Fraction b)
    {
            Fraction res;
            res.deno = a.deno * b.deno;
            res.nume = a.nume * b.nume;
            return reduction(res);
    }
    
    Fraction divide(Fraction a,Fraction b)
    {
            Fraction res;
            res.deno = a.deno * b.nume;
            res.nume = a.nume * b.deno;
            return reduction(res);
    }
    
    void showFrac(Fraction a)
    {
            a = reduction(a);
            if(a.nume < 0)
            {
                    printf("(");
            }
            if(a.deno == 1)
            {
                    printf("%lld",a.nume);
            }
            else if(abs(a.nume) > abs(a.deno))
            {
                    printf("%lld %lld/%lld",a.nume / a.deno,abs(a.nume) % a.deno,a.deno);
            }
            else
            {
                    printf("%lld/%lld",a.nume,a.deno);
            }
            if(a.nume < 0)
            {
                    printf(")");
            }
    }
    
    int main()
    {
            Fraction a,b;
            scanf("%lld/%lld%lld/%lld",&a.nume,&a.deno,&b.nume,&b.deno);
    
            showFrac(a);
            printf(" + ");
            showFrac(b);
            printf(" = ");
            showFrac(add(a,b));
            printf("
    ");
    
            showFrac(a);
            printf(" - ");
            showFrac(b);
            printf(" = ");
            showFrac(sub(a,b));
            printf("
    ");
    
            showFrac(a);
            printf(" * ");
            showFrac(b);
            printf(" = ");
            showFrac(times(a,b));
            printf("
    ");
    
            showFrac(a);
            printf(" / ");
            showFrac(b);
            printf(" = ");
            if(b.nume == 0)
            {
                    printf("Inf
    ");
            }
            else
            {
                    showFrac(divide(a,b));
                    printf("
    ");
            }
    
            return 0;
    }
    

    素数

    1、判断素数

    bool isPrime(int a)
    {
            if(a <= 1)   //1不是素数,也不是合数
                    return false;
            int tmp = (int)sqrt(1.0 * a);
            for(int i = 2;i <= tmp;i++)
            {
                    if(a % i == 0)
                            return false;
            }
            return true;
    }
    

    2、打素数表

    第一种方法是枚举判断。

    const int maxn = 10010;
    int prime[maxn],num = 0;
    
    void Prime_table()
    {
            for(int i = 2;i < maxn;i++)
            {
                    if(isPrime(i))
                    {
                            prime[num++] = i;
                    }
            }
    }
    

    第二种是Eratosthenes筛法,复杂度比枚举更优,代码更短。

    /* sieve[k] is false iff k is a prime */
    public static boolean[] primes (int n) {
        boolean[] sieve = new boolean[n + 1];
        sieve[0] = sieve[1] = true;
    
        for (int k = 2; k * k <= n; ++k) {
            if (!sieve[k]) {
                for (int j = k * k; j <= n; j += k) {
                    sieve[j] = true;
                }
            }
        }
        return sieve;
    }
    

    3、分解质因子
    注意:1要特判。

    //存储
    struct factor{
            int x,cnt; //x为质因子,cnt为该质因子个数
    }fac[20];
    
    int num = 0;  //记录不同因子个数
    //枚举小于等于sqrt(n)内的所有质因子,判断哪个是n的因子
    for(int i = 0;prime[i] <= sqrt(n);i++)
    {
            if(n % prime[i] == 0)
            {
                    fac[num].x = prime[i];
                    fac[num].cnt = 0;
                    while(n % prime[i] == 0)
                    {
                            fac[num].cnt++;
                            n /= primep[i];
                    }
                    num++;
            }
    }
    
    //如果n仍然大于1,说明n有一个大于sqrt(n)的质因子
    if(n != 1)
    {
            fac[num].x = n;
            fac[num++].cnt = 1;
    }
    
  • 相关阅读:
    Zabbix监控mysql配置及故障告警配置
    Tesseract-OCR 字符识别---样本训练
    Wex5案例使用JSON传输Thinkphp后端对接,以达成数据正常输出
    Linux内核分析:recv、recvfrom、recvmsg函数实现
    libevent源码分析:evmap_io_active_函数
    libevent源码分析:epoll后端实现
    监听套接字不可写?
    Linux内核分析:dup、dup2的实现
    Linux内核分析:打开文件描述符实现
    libevent源码分析:http-server例子
  • 原文地址:https://www.cnblogs.com/EIMadrigal/p/12130450.html
Copyright © 2011-2022 走看看