求一个数的因子数(改进版的试除法)

求一个数的因子数问题常用的方法是试除法,代码如下:

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

int main(){
    int n;cin >> n;
    vector<int> factor;
    factor.push_back(1);
    for(int i=2;i<=sqrt(n);++i){
        if(n % i == 0){
            factor.push_back(i);
            if(n/i != i) factor.push_back(n/i);
        }
    }
    if(n > 1) factor.push_back(n);
    for(auto x:factor) cout << x << " ";

    return 0;
}

一个数最多的因子数最多2×sqrt(n)个,这是上界,而在数据范围到2e9之前因子数最多的一个数也就1536个.这个是远小于上界的,所以我们可以改进一下算法.
根据唯一分解定理.一个数可以被分解为:p1k1×p2k2…pnkn这里的p都是质数.那一个数的因子其实就是这些质数不同次幂之间的组合,可以用搜索算法,一个一个枚举出来.就可以更快的计算出一个数的因子数了.
具体做法就是先进行质因数分解,然后dfs出答案.质因数分解的时候可以预处理出1-sqrt(n)的质数,加速这个过程.
代码

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>

const int N = 1e6;
using namespace std;

bool vis[N];
vector<int> prime;
void get_prime(int n){
    for(int i=2;i<=n;++i){
        if(!vis[i]) prime.push_back(i);
        for(auto x:prime){
            if(x*i > n) break;
            vis[x*i] = 1;
            if(i % x == 0) break;
        }
    }
}
int tot,n;
vector<int> factor;
vector<pair<int,int>> prime_factor;
void dfs(int u,int cur){
    if(u == tot){
        factor.push_back(cur);
        return;
    }
    int tmp = 1;
    for(int i=0;i<=prime_factor[u].second;i++){
        dfs(u+1,cur*tmp);
        tmp *= prime_factor[u].first;
    }
}
int main(){
    cin >> n;
    get_prime((int)sqrt(n));
    for(int i=2;i<=sqrt(n);++i){
        if(n%i == 0){
            int num = 0;
            while(n%i==0){
                num++;
                n/=i;
            }
            prime_factor.push_back(make_pair(i,num));
        }
    }
    if(n > 1) prime_factor.push_back(make_pair(n,1));
    tot = prime_factor.size();
    dfs(0,1);
    sort(factor.begin(),factor.end());
    for(auto x:factor) cout << x << " ";

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/106498841
今日推荐