唯一分解定理

唯一分解定理:

任何一个大于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;
            }
        }
    }
}
posted @ 2019-10-28 14:48  Emcikem  阅读(270)  评论(0编辑  收藏  举报