数学问题

1.主要内容

进制转换、最大公约数和最小公倍数、素数筛选、二分求幂、高精度整数

这一部分主要难点在于掌握一些经典的处理方法,还有就是时间复杂度和数据溢出的问题

2.取模运算

(1)计算机中的取模运算a%b,是先计算二者绝对值的模,之后再取和a一样的符号

(2)当计算结果为负值时,与理论结果并不相符。这是需要把负数的结果+b在对b取模,直到结果为正

(3)大数取模防止逸出

(a*b)%m=(a%m*b%m)%m

(a+b)%m=(a%m+b%m)%m

3.数位拆解

要求把输入数据的每位分别进行一些处理,最好的办法使用char数组输入

4.进制转换

(1)库函数方法

这个方法只适用于 已知输入数进制,输入输出都是int可以表示的范围(2^31-1)

使用scanf()输入规定进制的数到int,在使用printf()输出要求转化的机制数

void itoa(int value,char*string,int axis);该函数可以把整数转换成axis(2,8,16)表示的进制字符串,再用“%s”输出即可

int atoi(char *)

View Code

(2)手算原理

k进制转10进制:各位依权重k^(n-1)求和

10进制转k进制:先取余(对k),在/=k,不断循环,可得到从低到高的k进制数

View Code
View Code

5.最大公约数与最小公倍数

(1)英文分别为 greatest common divisor 和 least common multiple

(2)筛选G常用欧几里得算法:G(a,b)=G(b,a%b) 递归直到第二个形参为0时,返回第一个形参

筛选L常用到公式L=(a*b)/G,这个等式在一些数学题目里也常用到

View Code

6.素数

6.1单个素数的判断

(1)1是合数,不是素数

(2)2是素数,1和2需要单独考虑

(3)从i=2开始,到 i^2<=n(这里最好提前计算sqrt(n))结束,如果n可以整除i,那么它是合数;否则是素数

View Code

 6.2大范围内素数的筛选

(1)一般先利用init()函数,把题目中给定的取值上界内所有的素数都筛选出来

(2)从2开始,如果已经被标记为合数则跳过;如果没有则是素数,记录下来,并把它的倍数全都标记为合数(这里有技巧)

View Code

6.3计算素因数

结合6.2的思路,对于N而言:

理论上,大于sqrt(N)的素因数最多有一个

(1)筛选sqrt(N)(最好比这个数大一些)以内的素数,如果是因数,则N/=这个数(此处注意这个数可能是多重因数

(2)如果筛选完后,如果N不是1,说明存在一个大于sqrt(N)的素因数,也就是N现在的值

7.二分求幂问题

这个问题就是要在a b很大的情况下求a^b

(1)把b化成二进制的形式,如3^31=3^(1111)

(2)把结果写成多个项之积,每项都是前一项的平方,即3^(1111)=3^(1+2+4+8) =(3^1)(3^2) (3^4) (3^8)

(3)这种题通常让求最后结果MOD某个数的值,一定要每步都在ans和a两个地方分别MOD,否则会溢出

View Code

结合1.和7.的一个题

View Code

8.高精度整数

 (1)主要原理使用一个结构体存储位数超出c++限制的数字,无论是+-*/等运算符的重载原理都一样,即 

 tmp=a1[i](+*-)a2[i](+-)carry;

carry=tmp/10000;

tmp%=10000; 

 (2)有时间还可以看一下<bits/stdc++.h>这个库

 (3)这部分最容易错的是对数组下标的计算以及数组越界问题 必须要特别小心

 

View Code

posted on 2020-02-08 18:18  mingzhou_liu  阅读(137)  评论(0)    收藏  举报

导航