前言
本篇文章是luogu官方题单【数学1】基础数学问题 的相关知识点个人总结
埃氏筛 & 欧拉筛 (基础)
虽然理论上欧拉筛比埃氏筛快,但是因为埃氏筛有cache,实际运行比欧拉筛要快
目前本人只见过欧拉筛模版题会卡这个(乐),但其实埃氏筛稍微优化一下常数甚至比欧拉筛跑的还快
埃氏筛完全够用
- 埃氏筛 \(O(nloglogn)\)
//不用vector<ll>记录质数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n;
int main(){ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n;vector<bool> not_prime(n+1,false);not_prime[1]=true;for(ll i=2;i*i<=n;i++){for(ll j=i*i;j<=n;j+=i){not_prime[j]=true;}}return 0;
}
//记录小于等于n的质数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,q,k;
int main(){ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n>>q;vector<bool> not_prime(n+1,false);vector<ll> vec;not_prime[1]=true;for(ll i=2;i<=n;i++){if(!not_prime[i]){vec.push_back(i);for(ll j=i*i;j<=n;j+=i){not_prime[j]=true;}}}return 0;
}
欧拉筛 \(O(n)\)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,q,k;
int main(){ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n>>q;vector<bool> vis(n+1,true);vector<ll> vec;for(ll i=2;i<=n;i++){if(vis[i]){vec.push_back(i);}for(ll j=0;i*vec[j]<=n;j++){vis[vec[j]*i]=false;if(i%vec[j]==0){break;}}}return 0;
}
质因数 (很多题都用到了)
对于合数 \(x\),最大质因子不超过$ \sqrt x $
复杂度压到根号的原理
最大公因数 & 最小公倍数
- 最大公因数gcd
ll gcd(ll x,ll y){ return (y==0?x:gcd(y,x%y)); }
- 最小公倍数lcm
$ lcm(x,y)=\frac{x \cdot y}{gcd(x,y)}$
- 推导公式
$ gcd(x,y)=z \rightarrow gcd(x/z,y/z)=1 $
$ gcd(x,y)=\frac{x \cdot y}{lcm(x,y)}$
排列组合
$ C(n,m)=C(n-1,m-1)+C(n-1,m) $
$ C(n,m)=\frac{n!}{m!(n-m)!} $
欧拉函数(P3601签到题)
-
标准分解式:x的质因数从小到大幂之积
$ x=p_1^{k_1} p_2^{k_2} ... p_n^{k_n} $ -
欧拉函数:小于等于x的正整数中与x互质的数的个数
$ \phi(x)=\prod_{i=1}^n (p_i-1) \cdot p_{k_i-1} $
对于欧拉函数有个很巧妙的求法
因为 \(x\) 中本身就含有 \(p_i^{k_i}\)
先令 \(\phi(x)=x\)
找到 \(x\) 的质因数 \(p_i\) 后
对 \(\phi(x)\) 直接除 \(p_i\) 再乘 \(p_i-1\) 即可