[王道考研计算机机试指南--专题训练]Chapter4 数学问题

1.%运算

a%b=c

计算机中实现%运算的方法为,先求 ∣ a ∣ |a| a% ∣ b ∣ |b| b得到 c c c,然后将 c c c的正负与 a a a取为一样。
其中当a为负数,我们如果有需求保证 c c c为正数可以采用以下处理方法。

c=(c+b)%b=(a%b+b)%b

对于%运算同时还存在以下的特点:

(a*b)%c=((a%c)*(b%c))%c;
(a+b)%c=((a%c)+(b%c))%c;

2.数位拆解

将一个数的每个位数进行拆解然后存储在数组中,一般数学方法和字符串处理两种方法,若题目涉及到数学运算一般采用第一种方法,若直接对输入的数字进行操作得到结果则可以采用第二种方法。
习题链接:
特殊乘法 (九度教程第39题)
反序数(九度教程第 40 题)
对称平方数(九度教程第 41 题)
Digital Root(九度教程第 42 题)

3.进制转换

将k进制数 ( b n b n − 1 . . . b 3 b 2 b 1 b 0 ) k (b_nb_{n-1}...b_3b_2b_1b_0)_k (bnbn1...b3b2b1b0)k转化为10进制数d:
d = b 0 ∗ k 0 + b 1 ∗ k 1 + b 2 ∗ k 2 + , . . . , + b n ∗ k n d=b_0*k^0+b_1*k^1+b_2*k^2+,...,+b_n*k^n d=b0k0+b1k1+b2k2+,...,+bnkn
将10进制数d转化为k进制数:
通过d%k的到当前位,然后执行d=d/k,重复以上操作,直到d=0为止。
之所以上面提到10进制与其他进制之间的相互转换是因为,一般涉及到将m进制转化为n进制的问题,一般会将问题分为以下两个步骤进行求解:

①将m进制转化为10进制
②将10进制转化为n进制

习题链接:
A+B (九度教程第 43题 )
数制转换(九度教程第 44题)
进制转换(九度教程第 45 题)
八进制(九度教程第 46 题)

4.最大公约数(gcd)

对于求解a和b的最大公约数问题,需要分一下三种情况进行讨论。

  • 1>a,b均为0,最大公约数不存在
  • 2>a,b中有一个为0,另一个不为0,最大公约数为非零的数
  • 3>a,b均不为0,则需要按照a=b,b=a%b的过程进行迭代求解,知道b=0时,a即为最大公约数

习题链接:
最大公约数 (九度教程第 47题)

5.最大公倍数(gcd)

两个数的最小公倍数为两数的乘积除以它们的最大公约数。
习题链接:
最小公倍数(九度教程第48题)
Least Common Multiple(九度教程第 49 题)

6.素数筛法

素数筛:
若一个数不是素数,则必存在一个小于它的素数为其的因数。这个命题的正确性是显而易见的。

相关问题涉及到:
判断一个数是否为素数。
找到一个区间内符合某条件的素数。

技巧:打表法

习题链接:
素数判定 (九度教程第 50 题)
素数(九度教程第 51题)
Prime Number(九度教程第 52 题)
Goldbach’s Conjecture(九度教程第53 题)

7.分解素因数

对于所有大于等于2的整数均可以分解成素数的乘积,即其存在一组完全为素数的质因数。

习题链接:
质因数的个数(九度教程第54题)
整除问题(九度教程第 55 题)

8.二分求幂

关于二分幂的求解可以使得求幂的复杂度从O(n)下降到O(logn).
主要代码如下所示:
由于math.h中内置的pow(a,b)函数返回的结果是int类型的因此最终的求解结果很容易就会溢出整形的范围。所以这里我们可以根据快速幂的方法把pow函数改写为返回值为long long类型的,代码片段如下所示:

/*
description:利用二分求幂的方法求解a^b.
*/
long long binaryPower(long long a,long long b){
    long long ans=1;
    while(b!=0){//equals to b%2==1
        if(b&1){
            ans*=a;
        }
        a*=a;
        b/=2;
    }
    return ans;
}

该方法同样适用于矩阵的乘法,同时矩阵的幂次乘法可以用于求解斐波那契数列的第n项(这就是有名的快速幂算法),其时间复杂度为O(2^3*logn),比之间遍历一遍通项公式的O(n)的复杂度大大的下降了,但n的数值非常大的时候,快速幂。在编写矩阵快速幂的时候需要编写矩阵的二分求幂和矩阵乘法运算。
快速幂算法代码如下所示:详细见此博客

#include <iostream>
#include <vector>
using namespace std;
/*
description:利用二分求幂的方法求解a^b.
*/
long long binaryPower(long long a,long long b){
    if(b==0)return 1;
    long long ans=1;
    while(b!=0){//equals to b%2==1
        if(b&1){
            ans*=a;
        }
        a*=a;
        b>>=1;
    }
    return ans;
}
/*
description:实现两个矩阵的乘法
*/
vector<vector<int>> matrixMultiple(vector<vector<int>> A,vector<vector<int>>B){
    int rowsA = A.size();
    int colsA = A[0].size();
    int rowsB = B.size();
    int colsB = B[0].size();
    vector<vector<int>> res;//存储矩阵相乘的结果
    if(colsA!=rowsB){
        printf("two matrices cannot be multiplied!");
        return res;//两矩阵不能相乘,返回空
    }
    else{
        res.resize(rowsA);//初始化结果矩阵的大小
        for(int i=0;i<rowsA;i++){
            res[i].resize(colsB);
        }
        for(int i=0;i<rowsA;i++){
                for(int j=0;j<colsB;j++){
                    int sum=0;
                    for(int k=0;k<colsA;k++){
                        sum=sum+A[i][k]*B[k][j];
                        }
                    res[i][j]=sum;
                }
        }
    }
     return res;
}

vector<vector<int>> quickMatrixPower(vector<vector<int>> A,int b){
    int rows = A.size();
    int cols = A[0].size();
    vector<vector<int>> ans;
    if(rows!=cols)
    {
        printf("Only the square matrices can be imaginary!");
        return ans;
    }
    //初始化矩阵ans为单位矩阵
    ans.resize(rows);
    for(int i=0;i<cols;i++)
        ans[i].resize(cols);
    ans[0][0]=ans[1][1]=1;
    ans[1][0]=ans[0][1]=0;
    while(b){//利用二分求幂的方法计算矩阵的幂次方的方法
        if(b&1){
            ans = matrixMultiple(A,ans);
        }
        A=matrixMultiple(A,A);
        b>>=1;
    }
    return ans;
}
int main()
{
    vector<vector<int>>A ={{1,1},{1,0}};
    vector<vector<int>>ans;
    ans.resize(2);
    for(int i=0;i<2;i++)
        ans[i].resize(1);
    ans[0][0]=1;
    ans[1][0]=1;
    int n = 6;
    if(n==1)printf("%d\n",1);
    if(n==2)printf("%d\n",1);
    A = quickMatrixPower(A,n-2);
    ans = matrixMultiple(A,ans);
    printf("%d\n",ans[0][0]);
    return 0;
}

习题链接:
约数的个数(九度教程第 56 题)
人见人爱 A ^ B (九度教程第 57 题)
A sequence of numbers(九度教程第 58 题)
TrA(九度教程第 59 题)(矩阵快速幂,与二分求幂原理相同)

9.高精度整数

题型总结详见该文章:
java–BigInteger神器的开启姿势
习题链接:
a+b(九度教程第 60 题)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值