基础数学知识
这里讲一些最基础的数学知识,基本上都是一些题目的前置知识,你可以不用,但不能不会
题目集:vj地址
质数
什么是质数(素数)?
质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)
判断质数几种方法
问题: 求出 1∼n中质数的个数
1.暴力求解(n*√n)
int isPrime(int x){
for(int i=2;i*i<=x;++i){
if(x%i==0) return 0;
}
return 1;
}
2.诶氏筛法 O(nloglogn)
void getPrime(){
for(int i=2;i<=n;i++){
if(!st[i]){
primes[cnt++]=i;
for(int j=i;j<=n;j+=i) st[j]=true;//可以用质数就把所有的合数都筛掉;
}
}
}
3.线性筛法 O(n)
核心思想:
注意这个算法一直使用“某数×质数”去筛合数,又已经证明一个合数一定会被它的最小质因数
p
1
p_1
p1筛掉,所以我们唯一要担心的就是同一个合数是否会被“另外某数 ×
p
1
p_1
p1以外的质数”再筛一次导致浪费时间。
代码中,外层枚举 i = 1→n。对于一个 i,经过前面的腥风血雨,如果它还没有被筛掉,就加到质数数组 Prime[]中。下一步,是用 i 来筛掉一波数。
内层从小到大枚举 Prime[j]。i×Prime[j] 是尝试筛掉的某个合数,其中,我们期望 Prime[j]是这个合数的最小质因数 (这是线性复杂度的条件,下面叫做“筛条件”)。它是怎么得到保证的?
j 的循环中,有一句就做到了这一点:
if(i % Prime[j] == 0) break;
完整代码:
int primes[N], cnt; // 记录得到的素数
bool st[N]; // 标记元素是否被筛掉
void get_primes(){
//外层从2~n迭代,因为这毕竟算的是1~n中质数的个数,而不是某个数是不是质数的判定
for(int i=2;i<=n;i++){
if(!st[i]) primes[cnt++]=i;
for(int j=1;j<=cnt&&primes[j]*i<=n;j++){//primes[j]*i<=n,把大于n的合数都筛了就
//没啥意义了
st[primes[j]*i]=true;//用最小质因子去筛合数
//1)当i%primes[j]!=0时,说明此时遍历到的primes[j]不是i的质因子,那么只可能是此时的primes[j]<i的
//最小质因子,所以primes[j]*i的最小质因子就是primes[j];
//2)当有i%primes[j]==0时,说明i的最小质因子是primes[j],因此primes[j]*i的最小质因子也就应该是
//prime[j],之后接着用st[primes[j+1]*i]=true去筛合数时,就不是用最小质因子去更新了,因为i有最小
//质因子primes[j]<primes[j+1],此时的primes[j+1]不是primes[j+1]*i的最小质因子,此时就应该
//退出循环,避免之后重复进行筛选。
if(i%primes[j]==0) break;
}
}
}
约数
对于两个数a,b
其最大公约数(即 gcd):
辗转相除法:两数相除,取余数重复进行相除,直到余数为0时,前一个除数即为最大公约数。
int gcd(int a,int b)
{
return b>0 ? gcd(b,a%b):a;
}
其最小公倍数(即 lcm):
lcm(a,b)=a*b/gcd(a,b);
**
快速幂
**
long long fastPower(long long base, long long power) {
long long result = 1;
while (power > 0) {
if (power & 1) result = result * base % mod;
power >>= 1;//此处等价于power=power/2
base = (base * base) % mod;
}
return result;
}
求组合数
递推式:
const int mod = 1e9+7;
long long f[2010][2010];
for(int i=0;i<=2000;i++)
{
for(int j=0;j<=i;j++)
{
if(!j) f[i][j]=1;
else f[i][j]=(f[i-1][j-1]+f[i-1][j])%mod;
}
}
太小了,只能算千位
乘法逆元:
“取模”运算的运算法则:(具体的证明感兴趣的同学可以问度娘)
(a + b) % p = (a % p + b % p) % p (1)
(a - b) % p = (a % p - b % p ) % p (2)
(a * b) % p = (a % p * b % p) % p (3)
( a ÷ b ) % c= ( a % c ÷ b % c)% c --> 错的
想边乘边除边取模肯定是不可取的,
这时候就要用到著名的费马小定理了:
也就是说:a的逆元为a^(p-2)
直接用上面讲述的快速幂即可
简单博弈论
题目常以两人玩回合制游戏为背景,每轮都采取最优解,老熟人Alice和Bob。
Nim游戏 ----------题解链接
台阶-Nim游戏
集合-Nim游戏
拆分-Nim游戏
这里放一张Acwing基础课的知识点图,还是非常好的,对于算法小白把能用到的数学基本上都列举了,没买课的照着知识点学就行了