【数论学习笔记】 约数
定义:
都是废话,就不说了。
N的正约数集合——试除法:
依旧是试除法,和求质因数的分解基本一样,不过要扫描1到sqrt(n),而且若d为N的约数,N/d也会是约数。代码有空再放。
求1到N每个数的正约数集合——倍数法
对于每一个以d为约数的数,就是d的倍数,通过翻倍来求出。代码如下。
vector<int> factor[500010]; inline void bei(int n){ for(int i=1;i<=n;i++) for(int j=1;j<=n/i;j++) factor[i*j].push_back(i); for(int i=1;i<=n;i++){ for(int j=0;j<factor[i].size();j++) printf("%d ",factor[i][j]); puts(""); } }
最大公约数:
gcd(a,b) 表示 a 和 b 的最大公约数,lcm(a,b) 表示a和b的最小公倍数。gcd(a,b)*lcm(a,b)=a*b。
更相减损术:a>b gcd(a,b)=gcd(b,a-b)=gcd(a,a-b) gcd(2a,2b)=2gcd(a,b)。
欧几里得算法:gcd(a,b)=gcd(b,a mod b)
int gcd(int a,int b){ return b ? gcd(b,a%b) : a; }
欧拉函数:
表示1到N中与N互质的数的个数称为欧拉函数。
算数基本定理中,n=(p1^c1)*(p2^c2)……(pm^cm) 。
phi(n)=n * [(p1-1)/p1] * [(p2-1)/p2]…… [(pm-1)/pm] 。
代码。
inline int phi(int n){ int ans=n; for(int i=2;i<=sqrt(n);i++) if(n%i==0){ ans=ans/i*(i-1); while(n%i==0) n/=i; } if(n>1) ans=ans/n*(n-1); return ans; }