今天学习了算术基本定理和容斥定理, 内容偏难,留作以后查阅复习使用。
算术基本定理:
任何一个大于1的自然数N,如果N不为质数,那么N可以分解
成有限个质数的乘积,并且在不计次序的情况下,这种分解方式是唯一的。
举例:60=2*2*3*5;
公式表示:N = p1^r1*p2^r2*p3^r3*...*pn^rn;
(p1 < p2 < p3 <...< pn & pi is prime number and ri >= 0)
质因子分解代码实现:
int prm[N],sz;// prm提前预处理
map<int, int> f(int n){
map<int, int> ans;
for(int i = 0; i < sz && prm[i] * prm[i] <= n; i++){
while(n % prm[i] == 0){
ans[prm[i]]++;
n /= prm[i];
}
}
if(n != 1) ans[n] = 1;
return ans;
}
prm[N]为预打表处理,把需要范围内的素数打表。代码复杂度sqrt(n).
算术基本定理的应用:
1.求解数n的因子个数:
根据算术基本定理:N = p1^r1*p2^r2*p3^r3*...*pn^rn
设n%a==0,即a是n的因子之一;
也有a = p1^a1*p2^a2*p3^a3*...*pn^an
那么 0<=an<=r1;
所以因子个数 ans=(1 + r1) *(1 + r2) * (1 + r3) * ... * (1 + rn)
2.求数N的所有因子之和:
要求N的各因子之和
N = p1^r1*p2^r2*p3^r3*...*pn^rn
f(n)是积性函数,即f(a*b)=f(a)*f(b) a,b为素数;
设 f(n) = (p^(r+1) - 1) / (p - 1)
ans=(p1^(r1+1) - 1) / (p1- 1)*(p2^(r2+1) - 1) / (p2 - 1)*...*(pn^(rn+1) - 1) / (pn - 1)
3,在算术基本定理下看 GCD和LCM:
X=p1^x1*p2^x2*p3^x3*...*pn^xn
Y=p1^y1*p2^y2*p3^y3*...*pn^yn
GCD=P1^min(x1,y1)*P2^min(x2,y2)*P3^min(x3,y3)*...*Pn^min(xn,yn)
LCM=P1^max(x1,y1)*P2^max(x2,y2)*P3^max(x1,y1)*...*Pn^max(xn,yn)
容斥定理:
要计算几个集合并集的大小,我们要先将所有单个集合的大
小计算出来,然后减去所有两个集合相交的部分,再加回所
有三个集合相交的部分,再减去所有四个集合相交的部分,
依此类推,一直计算到所有集合相交的部分
若要求 AUBUC的面积 即 A+B+C-A∩B-A∩C-B∩C-A∩B∩C
二进制状态枚举;
int main(){
n <= 20 1e6
1e8
int n = 3;
for(int i = 0; i < (1 << n); i++){ // 相当于枚举所有的情况 时间复杂度o(2^n*n)
for(int j = 0; j < n ;j++){
printf("%d ", (i >> j )& 1);
}
puts("");
}
return 0;
}
容斥定理部分应用:
- 对于一个数字来说,区间有多少数字是它的倍数
- 发现有重叠部分
- 用容斥定理
- 假如当前枚举到的状态有两个数字a和b,那么区间中有多少
- 个数字即是a的倍数也是b的倍数呢?