初等数论
最大公约数
求法:gcd(a,b)=gcd(b,a%b)
证明:
假设存在整数n满足n|b&&n|a
那么我们可以设a=xn,b=yn
a%b=(xn)%(yn)=(x%y)*n
所以一定存在n|(a%b)
综上,a,b的公约数集一定等于b,a%b的公约数集
所以gcd(a,b)=gcd(b,a%b)
所以,我们只需要不断的让a=b,b=a%b直到b=0,这时a,b的最大公约数就是a
代码:
ll gcd(ll x,ll y){
if(!y)return x;
else return gcd(y,x%y);
}
质数筛法/线性筛
普通筛法:假如我们找到一个质数,就把所有他的倍数标记成合数,这样我们扫描到没有标记过的数时,就是质数
代码:
ll P[MAXN],cnt,n;
bool tag[MAXN];
void getP(){
for(int i=2;i<=n;i++){
if(!tag[i]){//没有标记
P[++cnt]=i;//存下质数
for(int j=i;j<=n;j+=i){
tag[j]=true;
}
}
}
}
这个时间复杂度已经比较优秀了,但我们还可以考虑优化
考虑这个算法的复杂度浪费在什么地方,很明显,一个合数每有一个质因子,他就会被标记一遍
例如:12=223,在扫描到2的时候被标记了一边,在3的时候又被标记了一遍
既然对于每一个质因子都会被扫描一边,那我们规定:每个合数只能被自己的最小质因子标记
这样,每个数就只会被标记一遍了
考虑实现:
我们定义一个s数组,s(i)表示i的最小质因子,分类讨论:
1.\(s(i)=0\) 即在前面的扫描中没有找到这个数的质数,那么\(s(i)=i,i\in P\)
2.\(s(i)\neq0\),i不是质数
找到s(i)后,我们枚举所有小于s(i)的数P(j),我们令s(i*P(j))=j
为什么是对的呢,我们知道\(i*P(j)\)的质因数要么是i的质因数要么是P(j),i不存在比s(i)更小的质因数,所以\(i*P(j)\)的最小质因数一定是P(j)
代码:
for(int i=2;i<=n;i++){
if(!s[i]){
P[++cnt]=i;
s[i]=cnt;
}
for(int j=1;j<=s[i];j++){
if(P[j]*i>n)break;
s[i*P[j]]=j;
}
}
逆元求解/线性同余方程组
欧拉定理
定义:我们定义欧拉函数\(\phi(x)\)为所有小于x的与x互质的数的个数
欧拉函数求解
我们将x分解质因数\(x=P_1^{c_1}*P_2^{c_2}...*P_n^{c_n}\)
那么就有\(\phi(x)=x*(1-\frac{1}{P_1})*(1-\frac{1}{P_2})...*(1-\frac{1}{P_n})\)
证明

浙公网安备 33010602011771号