唯一分解定理
唯一分解定理:
任何一个大于1的自然数 ,如果N不为质数,都可以唯一分解成有限个质数的乘积\(N = P_{1}^{a_{1}}P_{2}^{a_{2}}...P_{k} ^{a_{k}}\) ,这里\(P_{1} < P_{2} <...<P_{k}\)均为质数,其指数 \(a_{i}\)是正整数,k为不同的质数个数。
而在质数中只有2是偶数,也就是说N可以分解为\(2^{a_{1}}\)与一个奇数的乘积
求n的所有质因子
int tot = 0;
int divi[maxn];
void div(int n){
for(int i = 2; i * i <= n; i++){
if(n % i == 0){
divi[tot++] = i;
while(n % i == 0)n /= i;
}
}
if(n > 1)divi[tot++] = n;
}
同时记录指数
int tot = 0;
int divi[maxn];
int num[maxn];
void div(int n){
for(int i = 2; i * i <= n; i++){
if(n % i == 0){
divi[++tot] = i;
while(n % i == 0)n /= i,num[tot]++;
}
}
if(n > 1)divi[++tot] = n,num[tot]++;
}
求一个数的所有因子
void cal(ll n){
for(int i = 1; i * i <= n; i++){
if(n % i == 0){
cout << i << endl;
if(i * i != n)cout << n / i << endl;
}
}
}
优化版一分解定理
void divide(int n){//优化版一分解定理
for(int i = 1; i <= tot && pri[i] * pri[i] <= n; i++){
if(n % pri[i] == 0){
//操作
while(n % pri[i] == 0) n /= pri[i];
}
}
if(n > 1) //操作
}
约数个数
数n的因子个数为
\(\prod_{i = 1}^{k}(a_i + 1) = (a_{1}+1)*(a_{2}+1)...(a_{k}+1)\)
(因为\(p_{i}\)为0时也是一种情况)
时间复杂度\(O(\sqrt n)\)
ll cal(ll n){
ll ans = 1;
for(ll i = 2; i * i <= N; i++){
if(n % i == 0){
int tot = 0;
while(n % i == 0)n /= i, tot++;
ans *= (tot + 1);
}
}
if(n > 1)ans *= 2;
return ans;
}
约数之和
数n的因子之和为
\(\prod_{i = 1}^k(\sum_{j = 0}^{a_i} p_i^j) = (p_{1}^{0} + p_{1}^{1}+\dots +P_{1}^{a_1})*(p_{2}^{0} + p_{2}^{1}+\dots +P_{2}^{a_2})......*(p_{n}^{0} + p_{k}^{1}+\dots +P_{k}^{a_k})\)
$ = \prod_{i = 1}^k(\frac{(1 - p^{a_i+1})}{1 - p_i}) = \prod_{i = 1}k(\frac{p_i - 1}{p_i - 1}) \(
时间复杂度\)O(\sqrt n)$
//等比数列前n项和的递推公式S_n = S_(n - 1) * q + 1
ll cal(ll n){
ll ans = 1;
for(ll i = 2; i * i <= n; i++){
if(n % i == 0){
ll tmp = 1;
while(n % i == 0){
n /= i;
tmp = tmp * i + 1;
}
ans *= tmp;
}
}
if(n > 1)ans *= (1 + n);
return ans;
}
线性筛前n个数的约数个数和及约数和
前n个数的约数个数\(\sum_{i = 1}^{n}\lfloor\frac{n}{i}\rfloor\)
前n个数的约数和\(\sum_{i = 1}^{n}i* \lfloor\frac{n}{i } \rfloor\)
整除分块时间复杂度\(O(\sqrt n)\)
ll cal(ll n){
ll ans = 0;
for(ll l = 1, r; l <= n; l = r + 1){//枚举因子l
r = n / (n / l);//分块的最后一个数
ans += (r - l + 1) * (n / l);
}
return ans;
}
约数和
ll cal(ll n){
ll ans = 0;
for(ll l = 1, r; l <= n; l = r + 1){//枚举因子l
r = n / (n / l);//分块的最后一个数
ans += (n / l) * (r - l + 1) * (l + r) / 2;//约数是[l, r]
}
return ans;
}
线性筛前n个数的约数个数
d[i]表示i的约数个数, fac[i]表示i的最小质因子的次幂
时间复杂度\(O(n)\)
i为素数时,约数个数为2个,
①当\(i\% p[j] != 0\)时,\(gcd(i, p[j]) = 1\),由积性函数性质可得
d[i * pri[j]] = d[i] * d[pri[j]] = d[i] * 2,fac[i * p[j]] = 1(无平方因子)
②当\(i \% pri[j] == 0\)时
````d[i * pri[j]] = d[i] / (fac[i] + 1) * (fac[i] + 2), fac[i * pri[j]] = fac[i] + 1```
int pri[N], d[N], fac[N], tot;
bool vis[N];
void d_table(int N){
d[1] = 1;
for(int i = 2; i <= N; i++){
if(!vis[i]){
pri[++tot] = i;
d[i] = 2, fac[i] = 1;
}
for(int j = 1; j <= tot; j++){
if(i * pri[j] > N)break;
vis[i * pri[j]] = 1;
if(i % pri[j] == 0){
d[i * pri[j]] = d[i] / (fac[i] + 1) * (fac[i] + 2);
fac[i * pri[j]] = fac[i] + 1;
break;
}else{
d[i * pri[j]] = d[i] * 2;
fac[i * pri[j]] = 1;
}
}
}
}