Time limit excedeed error for large values

半腔热情 提交于 2020-04-07 08:01:13

问题


I have been given x and k, where x is the number of factors of a number A, and k is the number of prime factors of A. Given x and k, I have to find out whether such an A exists.

For example:

INPUT : 4 2 
OUTPUT : 1

Since 6 is a number that has 4 factors 1, 2, 3, 6 out of which 2 are prime(2, 3). Also it is given that x and k can have any values between 1 and 109.

Here is my code for the this:

long long int x, k;
scanf("%lld%lld", &x, &k);

int ans = 0;

bool stop = false;

for (long long int numbers = 1; numbers < pow(10, 9) && !stop; numbers++) {
    long long int noOfFactors = 0, noOfPrimes = 0;
    for (long long int a = 1; a <= numbers && !stop; a++) {
        if (numbers % a == 0) {
            noOfFactors += 1;
            if ((isprime(a)) == 1) {
                noOfPrimes += 1;
            }
         }
     }
     if (noOfFactors == x && noOfPrimes == k) {
         ans = 1;
         stop = true;
     } else
         ans = 0;
}   
printf("%d\n", ans);

Where isprime(x) returns 1 if x is prime else 0.

But while running the program, it shows TLE error. Can anyone help me out in optimising this algorithm, or if any other method exists, can you just explain it to me ? Any help in optimising this algorithm or using another method would be kindly appreciated.


回答1:


Let p1, p2, p3, … pk be the prime factors of some positive integer n. By the fundamental theorem of arithmetic, n can be represented as p1e1p2e2p3e3• … pkek for some positive integers e1, e2, e3, … ek. Furthermore, any such set of such positive integers represents one positive integer in this way.

Every factor of n can be represented as p1f1p2f2p3f3• … pkfk for some integers fi where 0 ≤ fiei.

Each fi can have ei+1 values from 0 to ei, so the number of factors of n is (e1+1)•(e2+1)•(e3+1)• … (ek+1).

Since each ei must be positive, each ei+1 must be at least 2. Now we can see that, if n has x factors, then x is expressible as a product of k integers each at least 2. Conversely, if x is expressible as a product of k integers each at least 2, that product gives us values for ei, which gives us a positive integer n that has x factors and k prime factors.

Therefore, a number with x factors and k prime factors exists if and only if x is expressible as a product of k integers each at least 2.

To test this, simply divide x by prime numbers, e.g., divide by 2 as many times as possible without a remainder, then by 3, then by 5, and so on. Once x has been divided by k−1 factors and the result is greater than 1, then we know x is expressible as a product of k integers each at least 2 (the last may be composite rather than a prime, such as 2•3•3•3•35). If x reaches 1 before or just as we have divided it by k−1 factors, then no such number exists.




回答2:


So let me summarize my comments of above to answer the question 'how can I make it more efficient?'

  1. Store the pow(10, 9) in a variable, so you don't have to recalculate it every time a for-loop will do it's next iteration.
  2. You can reduce the checking of primeNum to only 0 to its square, which makes sense, but if you don't feel comfortable, check out this question or wikipedia
  3. If you checked that a number isn't prime, make sure you won't recalculate that again in the execution of the program, because checking for prime, especially when a number is very big, is time-consuming.

I think that's the most you can do about calculating with brute-force on primes, since there hasn't been found a faster way yet to check on prime.




回答3:


First your implementation is too inefficient

  • Don't call a function inside the for loop like this

    for (long long int numbers = 1; numbers < pow(10, 9) && !stop; numbers++)
    

    pow will be called unnecessarily on each iteration. Save every constant to a variable before the loop. But in this case just use numbers < 1e9

  • To get all factors of n you just need to loop until sqrt(n). You're doing for (long long int a = 1; a <= numbers && !stop; a++) { if (numbers % a == 0) { so for example instead of only 104 loops for 108 you'll need 108 loops. If numbers % a == 0 then both a and numbers/a are factors of numbers

But the real issue here is that your algorithm is flawed. You can get all factors of A if you know the prime factors of A and their exponents. If A = p1m p2n ... pkp then A will have the following factors:

  • p1i for i = 1..m
  • p2i for i = 1..n
  • ...
  • pki for i = 1..p
  • Factors from 2 prime factors: p1ip2j, p1ip3j,... p1ipkj, p2ip3j, p2ip4j,... p2ipkj,... pk-1ipkj
  • Factors from 3 prime factors...
  • Factors from k prime factors

This is purely a combination counting issue that can be done easily without even knowing A. Notice that the number of factors from k prime factors has some relation to the number of factors from k-1 prime factors




回答4:


Your algorithm is very inefficient. Here are a few ideas:

  • reject obvious fails: if x < 2 or k <= 0 or x < k the answer is 0 without further testing.
  • do not mix floating point and integer arithmetics. Use 1000000000 instead of pow(10, 9).
  • the inner loop can be stopped much earlier than you do: only run it while a * a < numbers and add 2 divisors for each match. Add another divisor if a * a == numbers.
  • also stop the inner loop if noOfFactors > x or noOfPrimes > k.

The program will run faster, but still not fast enough, especially for large x and k. Solving this problem efficiently requires a mathematical approach: it does not depend which prime factors are involved in the factorisation to prove whether there are solutions. Here are a few hints for a more advanced analysis:

  • you know how many prime factors A has, the only unknowns are the powers of these prime factors in A.
  • you can compute the minimum number of factors for any given set of prime factors. This number is the total number of draws from the set, which is simply 2k. If n is less than this number for the given k, the answer is 0.
  • compute this number for small values of k, you will see that it grows very quickly, so the number of values of k to study is quite low. If the k given is larger, the answer is 0. In practice for k = 30 there are at least 230 factors (1073741824). So if k >= 30 the answer is no.
  • for the k given, compute the number of combinations for a given set of powers of the prime factors (a,b,c...) is (a+1)*(b+1)*(c+1).... You can use recursion to enumerate the powers such that a >= b >= c ... stop the recursion as soon as the result exceeds n. If you find a result equal to n, the answer is 1. This analysis should complete very quickly.


来源:https://stackoverflow.com/questions/61054171/time-limit-excedeed-error-for-large-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!