• A1 编程部分数学常识(C++代码实现)


    1-1 奇偶判断

    if((a&1) == 0)//判断a是否为偶,需要加上括号,    ! > 算术运算符 > 关系运算符 > && > || > 赋值运算符
    

    1-2 数组与int的转换(PAT A1069)

    int int_to_array(int a,int b[]){//低位在前
        int num = 0;
        while(a/10){
            b[num++] = a%10;
            a /= 10;    
        }
        b[num++] = a%10;
        return num;    
    }
    
    
    int array_to_int(int b[],int num){
        int sum = 0;
        for(int i = 0;i < num;++i){
            sum = sum*10+b[num-i-1];
        }
        return sum;
    }
    

    1-3 最大公约数/最小公倍数

    // (原理:gcd(a,b) = gcd(b,a%b)   :  greatest common divisor)
    // 使用条件:保证a >= b
    int gcb(int a,int b){
        if(a < b){
            swap(a,b);
        }
        if(b == 0)
            return a;
        else
            return gcb(b,a%b);
    }
    
    int gcd(int a,int b){   (使用3目运算符简化代码)
        if(a < b)
            swap(a,b);
        return !b ? a : gcd(b,a%b);
    }
    

    求最小公倍数: the least common multiple

    int d = gcd(a,b);// 求最小公倍数必须先求得最大公因数
    最小公倍数 = a*b/d; 为避免溢出,通常写成:a/d*b;
    

    1-4 分数的运算

    表示:
    struct Fraction{
        long long up,down;           //为避免溢出,一般采用long long型
    };
    /*三项规定:
        1.分数的正负性由分子决定
        2.分子为0,分母则为1
        3.分子分母没有除1以外的最大公约数
    */
    //将分式化成最简分式,所有需要加减乘除的分数都需要用reduction格式化
    Fraction reduction(Fraction result){
        if(result.down < 0){
                result.up = -result.up;
                result.down = -result.down;
        }
        if(result.up == 0){
            result.down = 1;
        }else{
            int d = gcd(abs(result.up),abs(result.down));
            result.up /= d;
            result.down /= d;
        }
        return result;
    }
    // 分式的加减乘除(以除法为例)//必须保证分式的分母不为0
    Fraction divide(Fraction f1,Fraction f2){
        Fraction result;
        result.up = f1.up * f2.down;
        result.down = f1.down * f2.up;
        return reduction(result);   //将分式化为最简分式
    }
    // 分数的加法:
    Fraction add_f(Fraction a,Fraction b){
        Fraction sum;
        sum.up = a.up * b.down + b.up * a.down;   //即便采用long long,这一步很容易溢出,慎用
        sum.down = a.down * b.down;
        sum = reduction(sum);
        return sum;
    }
    // 分式的输出(3种情况):
    void showResult(Fraction r){
        r = reduction(r);             //首先化为最简分式       
        if(r.down == 1)               //整数 
            printf("%lld",r.up);
        else if(abs(r.up) > 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);
        }
    }
    /*
    几个坑点:
    1.分数初始化为0,分子置0,分母置1  !,从而可以令自己定义的加减乘除可用。*/
    

    1-5 质数的判断,获取,分解

    定义:对任意正整数a(1<a<n),都有 n%a != 0成立,则n是素数。
    
    素数的判断O(n½):
    bool isPrime(int n){
        if(n <= 1) return false;
        int sqr = (int)sqrt(1.0*n); //注:sqrt的参数是浮点型
        for(int i = 2;i <= sqr;i++){
            if(n % i == 0) return false;
        }
        return true;
    }
    素数表的获取:
    法一:利用素数的判断枚举(n在10^5内)
    法二:Eratosthenes求质数方法(最简单易理解:O(n*loglogn))
    const int  maxn = 101;   //maxn:筛选到素数范围,pNum为筛选出的素数个数
    int prime[maxn],pNum = 0;
    bool p[maxn];  //标记数组:true代表不是素数,false代表不是素数,初始化都是素数,用memset初始化
    void Find_Prime(){
        for(int i = 2;i < maxn;i++){  //znj
            if(p[i] == false){
                prime[pNum++] = i;
                for(int j = i+i;j < maxn;j += i){
                    p[j] = true;
                }
            }
        }
    }
    

    质因数分解流程(需要获取质数表)

    为什么 1 不能被认为是质数?

    唯一分解定义(算术分解定理)

    思路:s1:枚举1~sqrt(n)范围内所有质因子p,判断p是否是否是n的因子:
            是:让n不断除以p,直到p不再是结果的质因子
            否:跳过
         s2:枚举完毕,n仍然大于1,n还有一个质因子就是n本身
    

    1-6 大整数的加减乘除

    • 这里的乘除仅仅实现了大整数与1位数字的乘除
    // (口诀:bign开始初始化,大+要进位,大-要去0,大*进位要剥削)
    struct bign{
        int d[1000];   //大整数位数可自行调整
        int len;
        bign(){  //构造函数初始化
            memeset(d,0,sizeof(d));
            len = 0;
        }
    };
    
    bign change(char str[]){          //将字符数组转换为大整数存储
        bign a;
        a.len = strlen(str);         
        for(int i = 0;i < a.len;++i){
            a.d[i] = str[a.len-i-1] - '0'; //逆序存储,保证低位在前,方便后面大整数的运算
        }
        return a;
    }
    
    int compare(bign a,bign b){
        if(a.len > b.len) return 1;
        else if(a.len < b.len) return -1;
        else{
            for(int i = a.len-1;i >= 0;i--){
                if(a.d[i] > b.d[i]) return 1;
                else return -1;
            }
            return 0;
        }
        return 0;
    }
    /**********大整数加法**********/  
    bign add(bign a,bign b){      //每一位由三部分组成:操作位1,操作位2,进位   a+b
        bign c;
        int carry = 0;//进位
        for(int i = 0;i < a.len || i < b.len;++i){  //低位在前方便进位         
            int temp = a.d[i]+b.d[i]+carry;
            c.d[c.len++] = temp%10;
            carry = temp/10;
        }
        if(carry != 0)   //不要忘记最后一位进位
            c.d[c.len++] = carry;
        return c;    
    }
    /********大整数减法****************/  
    bign sub(bign a,bign b){     //使用时需保证a > b,调用函数前需要一定的处理
        bign c;
        for(int i= 0;i < a.len || i < b.len;++i){
            if(a.d[i] < b.d[i]){
                a.d[i + 1]--;
                a.d[i] += 10;
            }
            c.d[c.len++] = a.d[i] - b.d[i];
        }
        while(c.len -1 >= 1 && c.d[c.len-1] == 0){ // 1.去掉多余的0  2.保证至少有一位数
            c.len--;
        }
        return c;
    }
    
    /*******大整数与整数相乘********/
    bign multi(bign a,int b){    //平常计算时是一位一位的算,由于正常大脑只能口算10以内的乘法,
        bign c;                 //计算机可以迅速算出基本数据类型的加减乘除,所以可以将整数作为一个整体乘上去
        int carry = 0;
        for(int i = 0;i < a.len;++i){
            int temp = a.d[i]*b + carry;
            c.d[c.len++] = temp%10;     
            carry = temp/10;    //高位作为新的进位
        }
        while(carry != 0){     //注意与加法进行区分
            c.d[c.len++] = carry%10;
            carry /= 10;
        }
        return c;
    }
    
    /******大整数与整数相除*******/
    bign divide(bign a,int b,int& r){    //除法未必除进,如需要余数需另外修改
        bign c;
        c.len = a.len;
        for(int i = a.len - 1;i >= 0;i--){  //除法是由高到低,其余数要保存下来
            r = r * 10 + a.d[i];          //和上一位余数结合
            if(r < b) c.d[i] = 0;          //不够除,该为为0
            else{      //够除
                c.d[i] = r/b;        //商
                r = r%b;          //获得新余数
            }    
        }
        
        while(c.len-1 >= 1 && c.d[c.len-1] == 0){  //去掉多余的0,保证还剩一个0
            --c.len;
        }
        return c;
    }
    

    2019年2月28日的笔记

    参考资料

    书籍《算法笔记》

  • 相关阅读:
    关于编码的问题(转)
    XML巩固
    浏览器兼容问题的解决方案
    JavaScript 全局变量命名空间生成函数
    表格的使用(转)
    post上传文件
    安装cocoapods
    UILabel内容模糊
    动态获取键盘高度
    iOS多线程同步锁
  • 原文地址:https://www.cnblogs.com/kfcuj/p/14805006.html
Copyright © 2020-2023  润新知