简体   繁体   English

找到一个数字的Prime因子的更好方法

[英]Better way of finding Prime Factors of a number

I'm solving an problem where you're given a number of test cases. 我正在解决一个问题,你会得到一些测试用例。 For each case, you're given a range(from x to y, inclusive). 对于每种情况,您都会获得一个范围(从x到y,包括在内)。 Within this range I must count all the numbers whose sum of prime factors is exactly K. 在这个范围内,我必须计算其素因子之和恰好为K的所有数字。

for example: 例如:

5 15 2

We know that there 5 numbers which have exactly 2 prime factors (6, 10, 12, 14, and 15). 我们知道有5个数字恰好有2个素因子(6,10,12,14和15)。

Now my code works perfectly, but it's too slow. 现在我的代码完美无缺,但速度太慢了。 And I was looking for a faster way to generate prime numbers via C++. 我正在寻找一种通过C ++生成素数的更快方法。 Here's my code. 这是我的代码。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <math.h>
#include <string>
#include <sstream>
#include <vector>
#include <iomanip>
#include <deque>
#include <queue>

#define Fill(s, v) memset(s, v, sizeof(s))
#define skipChar() (scanf("%c", &useless));
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar());x=(x<<3)+(x<<1)+_-'0');}while(0)
#define rekt return false;
#define notrekt return true;
char _, useless;

using namespace std;
typedef pair <int, int> intpair;
vector<int> primes;

void sieve(int n){
bool *prime = new bool[n +1];
fill(prime, prime + n+1, true);
prime[0] = false;
prime[1] = false;
int m = sqrt(n);
for(int i = 2; i <= m; i++)
    if(prime[i])
        for(int k = i*i; k <= n; k+=i){
            prime[k] = false;
            if(prime[k])primes.push_back(k);
        }
for(int i = 0; i <n; i++){
    if(prime[i])
        primes.push_back(i);
     }
}

int main()
{
int t;
int c = 1;
scan(t);
sieve(1000);
while(t--){
    int a, b, k;
    scan(a);
    scan(b);
    scan(k);
    int realCount = 0;
    for(int i = a; i <= b; i++){
        int count = 0;
        for(int j = 0; j < primes.size(); j++){
            if(i % primes[j] == 0){
                    count++;
            }
        }
        if(count == k)realCount++;
    }
    cout << "Case #"<< c << ": "<< realCount <<endl;
    c++;
    }
}

Thanks for the help! 谢谢您的帮助!

Thanks to everyone for contribution! 感谢大家的贡献! Here's Fast and Optimized Code! 这是快速优化的代码!

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <math.h>
#include <string>
#include <sstream>
#include <vector>
#include <iomanip>
#include <deque>
#include <queue>

#define F(a, s, val) fill(a, a + s, val);
#define skipChar() (scanf("%c", &useless));
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=_=getchar());x=(x<<3)+(x<<1)+_-'0');}while(0)
#define rekt return false;
#define notrekt return true;
char _, useless;

using namespace std;
typedef pair <int, int> intpair;

int *omega = new int[10000001];

void omg(){
    for(int i = 2; i < 10000000; i++)
            if(omega[i] == 0)
                    for(int j = i; j < 10000001; j+=i)
                            omega[j]++;
}

int main(){
    int t;
    int c = 1;
    F(omega, 10000001, 0);
    omg();
    scan(t);
    while(t--){
        int a, b, k;
        scan(a);
        scan(b);
        scan(k);
        int cc = 0;
        for(int i = a; i <= b; i++)
                    if(omega[i] == k)
                            cc++;
        printf("Case #%i: %i\n", c, cc);
        c++;
        }
    }

You properly pre-compute the primes over the desired range with the Sieve of Eratosthenes, which is good. 您可以使用Eratosthenes的Sieve正确地预先计算所需范围内的质数,这很好。 However, what you want to know is the number of distinct prime factors of each number in your range, not whether it is prime or composite. 但是,您想知道的是您范围内每个数字的不同素数因子的数量,而不是它是素数还是复合数。

That calculation can also be done by sieving. 该计算也可以通过筛分来完成。 Instead of keeping an array of booleans, keep an array of integers that count the number of distinct prime factors, and increment it for each prime factor found during sieving. 不是保留一个布尔数组,而是保持一个整数数组,计算不同素数因子的数量,并为筛选过程中找到的每个素因子增加它。

The sieving looks like this; 筛分看起来像这样; we call the array omega because that is the name that number theorists give to the function that returns the number of distinct factors of a number: 我们称这个数组为omega,因为这是理论师给函数的名称,它返回一个数字的不同因子的数量:

omega := makeArray(2..limit, 0)

for i from 2 to limit
    if omega[i] == 0
        for j from i to limit step i
            omega[j] := omega[j] + 1

The first few elements of the omega array are 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 1, 2, 2, 2, 2, 1, 2, 2‌​, 2, 1, 3 ( A001221 ). 欧米茄数组的前几个元素是1,1,1,1,2,1,1,1,2,1,2,1,2,2,1,1,2,1,2,2,21,2,1,2,1,2,1,3,1,1,2,2,2,2,1,2,2,2,1,3A001221 )。

Once you have omega , you can use it for all your queries: 一旦你有了omega ,你可以用它来解决所有问题:

function f(a, b, c)
    count := 0
    for k from a to b
         if omega[k] == c
             count := count + 1
    return count

For instance, f(5,15,2) = 5 (the set 6, 10, 12, 14, 15), f(2,10,1) = 7 (the set 2, 3, 4, 5, 7, 8, 9), f(24,42,3) = 2 (the set 30, 42), and f(2,10000000,7) = 1716 . 例如, f(5,15,2) = 5 (集合f(2,10,1) = 7f(2,10,1) = 7 (集合f(2,10,1) = 7 , 8,9), f(24,42,3) = 2 (组30,42), f(2,10000000,7) = 1716

If your range is too large to be conveniently sieved, you will have to factor each number in the range and count those with the correct number of distinct factors. 如果您的范围太大而不能方便地筛分,则必须考虑该范围内的每个数字,并计算具有正确数量的不同因子的数字。

your sieve function could possibly be optimised like this. 您的筛选功能可能会像这样优化。

vector<int> siev(int max) {
    vector<int> ret;
    bool isPrime[max];

    for(int i=2; i<max; i++) isPrime[i]=true; // reset all bits

    for(int i=2; i<max; i++) {
        if(isPrime[i]) {
            ret.push_back(i);
            for(int j=i*i; j<max; j+=i) {
                isPrime[j]=false;
            }
        }
    }

    return ret;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM