数学算法
5、数学问题
套路:熟悉常见题目
该部分不涉及很深的算法,却与数学息息相关,不需要特别的数学知识,只要掌握简单的数理逻辑即可。
最大公约数
int gcd(int a,int b){return !b?a:gcd(b,a%b);}这段代码十分简洁,并且实现了如果a<b,先互换。辗转相除法也称欧几里得算法。最小公倍数,在最大公约数的基础上计算,为
ab/gcd(a,b)
5.2 常用math函数
fabs(double x)floor(double x)向下取整ceil(double x)向上取整pow(double r,double p)返回r^psqrt(double x)log(double x)返回double型变量的以自然对数为底的对数sin(double x)、cos(double x)、tan(double x)pi=acos(-1)asin(double x)、acos(double x)、atan(double x)round(double x)四舍五入、返回类型也是double
5.3 日期处理
5.4 分数的四则运算
套路:实际做题过程中,还是套晴神模板最好,不需要单独设符号位,符号位在分子上即可,每次运算后化简。
建立分数结构类,实现加减乘除运算,符号位不用单独处理,计算时先不管分母正负,处理结果时如果分母为负,令分子分母同时取相反数即可,每次运算结束需要进行约分(注意分子不为0时除以gcd,为0时令分母为1)
5.5 质数、质因子分解
套路:大量质数时素数筛法,少量时用is_prime函数
is_prime函数O(n^1/2)或者用数组记录过程结果的筛素数法O(nloglogn)。
对于质因子分解,首先看因子分解,如果一个数存在除1和它本身之外的其他因子,那么必定是在sqrt(n)两侧成对出现的。对于质因子而言,可以得到,要么所有的质因子都小于sqrt(n),要么只有一个质因子大于sqrt(n),所以,质因子分解可以先判断2-sqrt(n)之间的所有质数是否是其质因子,最后再判断除去这些质因子后是否为1,否的话说明这是一个比sqrt(n)大的质因子。
5.6 高精度
套路:写的多了,问题就少了
实现大整数类,包括运算:高精度加减法、高精度与低精度的乘除法。
java大数
5.7 扩展欧几里得算法
ax+by=gcd(a,b).如何求得x,y。边界条件,b=0时x=1,y=0;根据辗转相除法递推可得递推公式x1=y2;y1=x2-(a/b) * y2;
方程ax+by=c的整数解,直接用扩展欧几里得算法,因为ax+by=gcd已知
同余式ax=c(mod m)求解,即ax+my=c求解,有解的条件是c%gcd(x,m)==0
逆元的求解。a,b,m>0,且ab=1(mod m),则称a,b互为模m的逆元
常用取模1e9+7
1000000007是一个质数
int32位的最大值为2147483647,所以对于int32位来说1000000007足够大
int64位的最大值为2^63-1,对于1000000007来说它的平方不会在int64中溢出
所以在大数相乘的时候,因为(a∗b)%c=((a%c)∗(b%c))%c,所以相乘时两边都对1000000007取模,再保存在int64里面不会溢出
5.8 组合数
第一个问题:求n!有多少个质因子P
比如10!中有2的质因子个数可表示为:有因子2的个数为10/2,有因子2^2的个数为10/2^2,有因子2^3的个数为10/2^3
可以递归求解,也可迭代求解。
即n!中有 $\frac{n}{p}+\frac{n}{p^2}+\frac{n}{p^3}+……$ 个质因子p,其中除法均为向下取整
第二个问题:组合数的计算
$C_m^n=\frac{m!}{n!(m-n)!}$
方法一就是通过定义直接计算,但是因为阶乘相当庞大,此种方法计算组合数能接受的数据范围很小。
方法二通过递归公式计算 $Cm^n=C{m-1}^n+C_{m-1}^{n-1}$
方法三通过定义变形来计算$C_m^n=\frac{(m-n+1)(m-n+2)……(m-n+n)}{n!}$,应注意到分子分母均为n项,先计算(m-n+1)/1,乘以(m-b+2)/2,不断乘以(m-n+i).
第三个问题:如何计算$C_n^m\%P$
掌握第一种方法即可,在组合数的计算的递归公式法上改进
5.9 错误重排问题
用A、B、C、D………表示写着n位友人名字的信封,a、b、c、d………表示n份相应的信,把n份信装错的总数记为D(n),那么n-1份信封装错的总数就是D(n-1)。 现在,假设这样一种情况,把a错装进B中,那么对于信b有以下两种分法: 1. b装入A中,这样剩下的(n-2)份信和信封A、B,和信a、b就没有任何关系了,所以这时候装错的可能性总共有D(n-2)。 2. b不一定装入A中,那么就有可能装入A、C、D等其余除B之外的信封了,这时总共就是(n-1)种装错的可能性了。 所以对于信b来说,总共有D(n-2)+D(n-1)种装错的可能性。所以最后除a之外还有(n-1)封信,所以最终的关系式如下: D(n)=(n-1)*[D(n-1)+D(n-2)]
5.10 斐波那契数列
想出递推公式最重要
5.11 约瑟夫问题
n个人围成一个圈,每个人分别标注为1、2、...、n,要求从1号从1开始报数,报到k的人出圈,接着下一个人又从1开始报数,如此循环,直到只剩最后一个人时,该人即为胜利者。例如当n=10,k=4时,依次出列的人分别为4、8、2、7、3、10,9、1、6、5,则5号位置的人为胜利者。给定n个人,请你编程计算出最后胜利者标号数。
约瑟夫问题,创新解法虽然分析复杂,但是代码却十分简洁明了,时间O(n),空间O(1),这就是数学的魅力。
主要思想:n个人第一个删除的人的秩为(k-1)%n,假如我们已经知道了n-1个人时,最后胜利者的编号为x,利用映射关系逆推,就可以得出n个人时,胜利者的编号为(x+k)%n(要注意的是这里是按照映射后的序号进行的)。可以总结为:
Last updated
Was this helpful?