Related
I should implement this summation in C ++. I have tried with this code, but with very high numbers up to 10 ^ 12 it takes too long.
The summation is:
For any positive integer k, let d(k) denote the number of positive divisors of k (including 1 and k itself).
For example, for the number 4: 1 has 1 divisor, 2 has two divisors, 3 has two divisors, and 4 has three divisors. So the result would be 8.
This is my code:
#include <iostream>
#include <algorithm>
using namespace std;
int findDivisors(long long n)
{
int c=0;
for(int j=1;j*j<=n;j++)
{
if(n%j==0)
{
c++;
if(j!=(n/j))
{
c++;
}
}
}
return c;
}
long long compute(long long n)
{
long long sum=0;
for(int i=1; i<=n; i++)
{
sum += (findDivisors(i));
}
return sum;
}
int main()
{
int n, divisors;
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
cin >> n;
cout << compute(n);
}
I think it's not just a simple optimization problem, but maybe I should change the algorithm entirely.
Would anyone have any ideas to speed it up? Thank you.
largest_prime_is_463035818's answer shows an O(N) solution, but the OP is trying to solve this problem
with very high numbers up to 1012.
The following is an O(N1/2) algorithm, based on some observations about the sum
n/1 + n/2 + n/3 + ... + n/n
In particular, we can count the number of terms with a specific value.
Consider all the terms n/k where k > n/2. There are n/2 of those and all are equal to 1 (integer division), so that their sum is n/2.
Similar considerations hold for the other dividends, so that we can write the following function
long long count_divisors(long long n)
{
auto sum{ n };
for (auto i{ 1ll }, k_old{ n }, k{ n }; i < k ; ++i, k_old = k)
{ // ^^^^^ it goes up to sqrt(n)
k = n / (i + 1);
sum += (k_old - k) * i;
if (i == k)
break;
sum += k;
}
return sum;
}
Here it is tested against the O(N) algorithm, the only difference in the results beeing the corner cases n = 0 and n = 1.
Edit
Thanks again to largest_prime_is_463035818, who linked the Wikipedia page about the divisor summatory function, where both an O(N) and an O(sqrt(N)) algorithm are mentioned.
An implementation of the latter may look like this
auto divisor_summatory(long long n)
{
auto sum{ 0ll };
auto k{ 1ll };
for ( ; k <= n / k; ++k )
{
sum += n / k;
}
--k;
return 2 * sum - k * k;
}
They also add this statement:
Finding a closed form for this summed expression seems to be beyond the techniques available, but it is possible to give approximations. The leading behavior of the series is given by
D(x) = xlogx + x(2γ - 1) + Δ(x)
where γ is the Euler–Mascheroni constant, and the error term is Δ(x) = O(sqrt(x)).
I used your brute force approach as reference to have test cases. The ones I used are
compute(12) == 35
cpmpute(100) == 482
Don't get confused by computing factorizations. There are some tricks one can play when factorizing numbers, but you actually don't need any of that. The solution is a plain simple O(N) loop:
#include <iostream>
#include <limits>
long long compute(long long n){
long long sum = n+1;
for (long long i=2; i < n ; ++i){
sum += n/i;
}
return sum;
}
int main()
{
std::cout << compute(12) << "\n";
std::cout << compute(100) << "\n";
}
Output:
35
482
Why does this work?
The key is in Marc Glisse's comment:
As often with this kind of problem, this sum actually counts pairs x,
y where x divides y, and the sum is arranged to count first all x
corresponding to a fixed y, but nothing says you have to keep it that
way.
I could stop here, because the comment already explains it all. Though, if it didn't click yet...
The trick is to realize that it is much simpler to count divisors of all numbers up to n rather than n-times counting divisors of individual numbers and take the sum.
You don't need to care about factorizations of eg 123123123 or 52323423 to count all divisors up to 10000000000. All you need is a change of perspective. Instead of trying to factorize numbers, consider the divisors. How often does the divisor 1 appear up to n? Simple: n-times. How often does the divisor 2 appear? Still simple: n/2 times, because every second number is divisible by 2. Divisor 3? Every 3rd number is divisible by 3. I hope you can see the pattern already.
You could even reduce the loop to only loop till n/2, because bigger numbers obviously appear only once as divisor. Though I didn't bother to go further, because the biggest change is from your O(N * sqrt(N)) to O(N).
Let's start off with some math and reduce the O(n * sq(n)) factorization to O(n * log(log(n))) and for counting the sum of divisors the overall complexity is O(n * log(log(n)) + n * n^(1/3)).
For instance:
In Codeforces himanshujaju explains how we can optimize the solution of finding divisors of a number.
I am simplifying it a little bit.
Let, n as the product of three numbers p, q, and r.
so assume p * q * r = n, where p <= q <= r.
The maximum value of p = n^(1/3).
Now we can loop over all prime numbers in a range [2, n^(1/3)]
and try to reduce the time complexity of prime factorization.
We will split our number n into two numbers x and y => x * y = n.
And x contains prime factors up to n^(1/3) and y deals with higher prime factors greater than n^(1/3).
Thus gcd(x, y) = 1.
Now define F(n) as the number of prime factors of n.
From multiplicative rules, we can say that
F(x * y) = F(x) * F(y), if gcd(x, y) = 1.
For finding F(n) => F(x * y) = F(x) * F(y)
So first find F(x) then F(y) will F(n/x)
And there will 3 cases to cover for y:
1. y is a prime number: F(y) = 2.
2. y is the square of a prime number: F(y) = 3.
3. y is a product of two distinct prime numbers: F(y) = 4.
So once we are done with finding F(x) and F(y), we are also done with finding F(x * y) or F(n).
In Cp-Algorithm there is also a nice explanation of how to count the number of divisors on a number. And also in GeeksForGeeks a nice coding example of how to count the number of divisors of a number in an efficient way. One can check the articles and can generate a nice solution to this problem.
C++ implementation
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 11;
bool prime[maxn];
bool primesquare[maxn];
int table[maxn]; // for storing primes
void SieveOfEratosthenes()
{
for(int i = 2; i < maxn; i++){
prime[i] = true;
}
for(int i = 0; i < maxn; i++){
primesquare[i] = false;
}
// 1 is not a prime number
prime[1] = false;
for(int p = 2; p * p < maxn; p++){
// If prime[p] is not changed, then
// it is a prime
if(prime[p] == true){
// Update all multiples of p
for(int i = p * 2; i < maxn; i += p){
prime[i] = false;
}
}
}
int j = 0;
for(int p = 2; p < maxn; p++) {
if (prime[p]) {
// Storing primes in an array
table[j] = p;
// Update value in primesquare[p * p],
// if p is prime.
if(p < maxn / p) primesquare[p * p] = true;
j++;
}
}
}
// Function to count divisors
int countDivisors(int n)
{
// If number is 1, then it will have only 1
// as a factor. So, total factors will be 1.
if (n == 1)
return 1;
// ans will contain total number of distinct
// divisors
int ans = 1;
// Loop for counting factors of n
for(int i = 0;; i++){
// table[i] is not less than cube root n
if(table[i] * table[i] * table[i] > n)
break;
// Calculating power of table[i] in n.
int cnt = 1; // cnt is power of prime table[i] in n.
while (n % table[i] == 0){ // if table[i] is a factor of n
n = n / table[i];
cnt = cnt + 1; // incrementing power
}
// Calculating the number of divisors
// If n = a^p * b^q then total divisors of n
// are (p+1)*(q+1)
ans = ans * cnt;
}
// if table[i] is greater than cube root of n
// First case
if (prime[n])
ans = ans * 2;
// Second case
else if (primesquare[n])
ans = ans * 3;
// Third case
else if (n != 1)
ans = ans * 4;
return ans; // Total divisors
}
int main()
{
SieveOfEratosthenes();
int sum = 0;
int n = 5;
for(int i = 1; i <= n; i++){
sum += countDivisors(i);
}
cout << sum << endl;
return 0;
}
Output
n = 4 => 8
n = 5 => 10
Complexity
Time complexity: O(n * log(log(n)) + n * n^(1/3))
Space complexity: O(n)
Thanks, #largest_prime_is_463035818 for pointing out my mistake.
My program prints all prime numbers from this expression:
((1 + sin(0.1*i))*k) + 1, i = 1, 2, ..., N.
Input Format:
No more than 100 examples. Every example has 2 positive integers on the same line.
Output Format:
Print each number on a separate line.
Sample Input:
4 10
500 100
Sample Output:
5
17
But my algorithm is not efficient enough. How can I add Sieve of Eratosthenes so it can be efficient enough to not print "Terminated due to timeout".
#include <iostream>
#include <cmath>
using namespace std;
int main() {
long long k, n;
int j;
while (cin >> k >> n) {
if (n>1000 && k>1000000000000000000) continue;
int count = 0;
for (int i = 1; i <= n; i++) {
int res = ((1 + sin(0.1*i)) * k) + 1;
for (j = 2; j < res; j++) {
if (res % j == 0) break;
}
if (j == res) count++;
}
cout << count << endl;
}
system("pause");
You can improve your speed by 10x simply by doing a better job with your trial division. You're testing all integers from 2 to res instead of treating 2 as a special case and testing just odd numbers from 3 to the square root of res:
// k <= 10^3, n <= 10^9
int main() {
unsigned k;
unsigned long long n;
while (cin >> k >> n) {
unsigned count = 0;
for (unsigned long long i = 1; i <= n; i++) {
unsigned long long j, res = (1 + sin(0.1 * i)) * k + 1;
bool is_prime = true;
if (res <= 2 || res % 2 == 0) {
is_prime = (res == 2);
} else {
for (j = 3; j * j <= res; j += 2) {
if (res % j == 0) {
is_prime = false;
break;
}
}
}
if (is_prime) {
count++;
}
}
cout << count << endl;
}
}
Though k = 500 and n = 500000000 is still going to take forty seconds or so.
EDIT: I added a 3rd mean to improve efficiency
EDIT2: Added an explanation why Sieve should not be the solution and some trigonometry relations. Moreover, I added a note on the history of the question
Your problem is not to count all the prime numbers in a given range, but only those which are generated by your function.
Therefore, I don't think that the Sieve of Eratosthenes is the solution for this particular exercise, for the following reason: n is always rather small while k can be very large. If kis very large, then the Sieve algorithm would have to generate a huge number of prime numbers, for finally use it for a small number of candidates.
You can improve the efficiency of you program by three means:
Avoid calculating sin(.) every time. You can use trigonometric relations for example. Moreover, first time you calculate these values, store them in an array and reuse these values. Calculation of sin()is very time consuming
In your test to check if a number is prime, limit the search to sqrt(res). Moreover, consider make the test with odd j only, plus 2
If a candidate res is equal to the previous one, avoid redoing the test
A few trigonometry
If c = cos(0.1) and s = sin(0.1), you can use the relations :
sin (0.1(i+1)) = s*cos (0.1*i) + c*sin(0.1*i))
cos (0.1(i+1)) = c*cos (0.1*i) - s*sin(0.1*i))
If n were large, it should be necessary to recalculate the sin() by the function regularly to avoid too much rounding error calculation. But it should not be the case here as n is always rather small.
However, as I mentioned, it is better to use only the "memorization" trick in a first step and check if it is enough.
A note on the history of this question and why this answer:
Recently, this site received several questions " how to improve my program, to count number of prime numbers generated by this k*sin() function ..." To my knowledge, these questions were all closed as duplicate, under the reason that the Sieve is the solution and was explained in a previous similar (but slightly different) question. Now, the same question reappeared under a slightly different form "How can I insert the Sieve algorithm in this program ... (with k*sin() again)". And then I realised that the Sieve is not the solution. It is not a criticism to previous closes as I made the same mistake in the understanding on the question. However, I think it is time to propose a new solution, even it is does not match the new question perfectly
When you make use of a simple Wheel factorization, you can obtain a very nice speedup of your code. Wheel factorization of order 2 makes use of the fact that all primes bigger than 3 can be written as 6n+1 or 6n+5 for natural n. This means that you only have to do 2 divisions per 6 numbers. Or even further, all primes bigger than 5 can be written as 30n+m, with m in {1,7,11,13,17,19,23,29}. ( 8 divisions per 30 numbers).
Using this simple principle, you can write the following function to test your primes (wheel {2,3}):
bool isPrime(long long num) {
if (num == 1) return false; // 1 is not prime
if (num < 4) return true; // 2 and 3 are prime
if (num % 2 == 0) return false; // divisible by 2
if (num % 3 == 0) return false; // divisible by 3
int w = 5;
while (w*w <= num) {
if(num % w == 0) return false; // not prime
if(num % (w+2) == 0) return false; // not prime
w += 6;
}
return true; // must be prime
}
You can adapt the above for the wheel {2,3,5}. This function can be used in the main program as:
int main() {
long long k, n;
while (cin >> k >> n) {
if (n>1000 && k>1000000000000000000) continue;
int count = 0;
for (int i = 1; i <= n; i++) {
long long res = ((1 + sin(0.1*i)) * k) + 1;
if (isPrime(res)) { count++; }
}
cout << count << endl;
}
return 0;
}
A simple timing gives me for the original code (g++ prime.cpp)
% time echo "6000 100000000" | ./a.out
12999811
echo "6000 100000000" 0.00s user 0.00s system 48% cpu 0.002 total
./a.out 209.66s user 0.00s system 99% cpu 3:29.70 total
while the optimized version gives me
% time echo "6000 100000000" | ./a.out
12999811
echo "6000 100000000" 0.00s user 0.00s system 51% cpu 0.002 total
./a.out 10.12s user 0.00s system 99% cpu 10.124 total
Other improvements can be made but might have minor effects:
precompute your sine-table sin(0.1*i) for i from 0 to 1000. This will avoid recomputing those sines over and over. This however, has a minor impact as most time is wasted on the primetest.
Checking if res(i) == res(i+1): this has barely any impact as, depending on n and k most consecutive res are not equal.
Use a lookup table, might be handier, this does have an impact.
original answer:
My suggestion is the following:
Precompute your sinetable sin(0.1*i) for i from 0 to 1000. This will avoid recomputing those sines over and over. Also, do it smart (see point 3)
Find the largest possible value of res which is res_max=(2*k)+1
Find all primes for res_max using the Sieve of Eratosthenes. Also, realize that all primes bigger than 3 can be written as 6n+1 or 6n+5 for natural n. Or even further, all primes bigger than 5 can be written as 30n+m, with m in {1,7,11,13,17,19,23,29}. This is what is called Wheel factorization. So do not bother checking any other number. (a tiny bit more info here)
Have a lookup table that states if a number is a prime.
Do all your looping over the lookup table.
Is there any way to improve the running time for this program? I get time limit exceed error from the online judge, and it seems like my program is running slow?
So, this is the question for this program: http://www.spoj.com/problems/PRIME1/
My code (language c):
#include <stdio.h>
void FindPrime (int m, int n)
{
int i, prime = 1;
if (m <= n)
{
for (i = m - 1; i > 1; i--)
{
if (m % i == 0)
{
prime = 0;
break;
}
}
if (prime == 1 && m != 1)
printf ("%d\n", m);
FindPrime (m + 1, n);
}
}
int main ()
{
int num1, num2, i, cases;
scanf ("%d", &cases);
while (cases != 0)
{
scanf ("%d %d", &num1, &num2);
FindPrime (num1, num2);
printf ("\n");
cases--;
}
return 0;
}
To solve this question you need to learn "Sieve of Eratosthenes".
First, get the idea of how it works from here. But, this is not enough to solve this question. Since, the complexity of the algorithm is O(n.log(log(n))). Therefore, if we put n = 1000000000. It will surely fail to execute.
Now, time to optimize it. Read it from here. But, we are done yet.
(Please read this section after you are done with the above two) Since we are to find the prime numbers is the range [m,n]. So, first create a list of prime numbers (let's call it primeList) between the range of 2 to 32000 using sieve of Eratosthenes (sqrt(10^9) = 31622.7, which is less then 32000). Now, check for every number k in the range of [m,n]
3.1. If the number k is in the range of 2-32000, and the number is in primeList. Print it.
3.2. If the number k > 32000, and is not divisible by all the numbers which are <= sqrt(k) and also in primeList. Print it. Else, ignore or don't print it. ( mind it '1' is not prime number).
You may check my solution. But, it is implemented slightly different than i explained although the concept applied is same.
Your code it calculating/listing the prime numbers between to numbers m & n cases number of times. Now you algorithm takes O(n) time for each value of m & hence total time taken by your code for a single case is O(n x m) or O(n^2) times..So in total the time taken is cases * O(n^2).. This is bad..Use some better algorithm to ease the complexity..
Check this modified version of Sieve of Eratosthenes
#include <stdio.h>
#define SIZE (int)(sizeof(boolean) / sizeof(int))
int main(){
int up,low;
int i,j;
printf("\nEnter the upper limit: ");
scanf("%d", &up);
printf("\nEnter the lower limit: ");
scanf("%d", &low);
int boolean[up];
int list[up];
for(i = 0; i < SIZE; i++){
boolean[i] = 1;
list[i] = 2 + i;
}
for(i = 0; i <= up; i++){
if (boolean[i] == 1)
for(j = i +1; j < SIZE; j++)
if(list[j] % list[i] == 0)
boolean[j] = 0;
}
for(i = 0; i < SIZE; i++)
if(boolean[i] == 1 && list[i] >= low && list[i] <= up)
printf("%d ", list[i]);
printf("\n");
return 0;
}
This will not visit one number more than once & hence will reduce the complexity in logarithmic scale.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
For the problem 10139 - Factovisors on UVa Online Judge, 2 numbers n and m are given, and we need to check whether m divides n!.
I use the algorithm:
Generate primes till const number
Take m and get its primes factor
For each prime in m's factors, calculate getpower function for n and compare them
I test different cases it give me also Wrong Answer, any suggestion?
Here's my code:
bool Factovisor (int n, int m) {
/* Special Cases */
if(n==0 && m!=1 )
return false;
else if(n==0&&m==1)
return true;
else if(m==0)
return false;
else if(m==n||m==1)
return true;
else if (n >= m)
return true;
else {
vector <factores> factores_in_m;
int index = 0;
int k=m;
/* first I generate all primes in primes vector */
for (int i = 0; i < primes.size(); i++) {
if (primes[i] > k) {
break;
} else {
/* factores is struct contain the prime and count*/
factores f = {primes[i], 0};
while (k % primes[i] == 0) {
f.count += 1;
k = k / primes[i];
}
if (f.count) {
factores_in_m.push_back(f);
}
}
}
if (k > 1) {
if (n < k) {
return false;
} else {
factores f;
f.prime= k;
f.count =1;
factores_in_m.push_back(f);
}
}
for (int i = 0; i < factores_in_m.size(); i++) {
if (factores_in_m[i].count - get_powers(n, factores_in_m[i].prime) > 0) {
return false;
}
}
return true;
}
}
int get_powers (int n, int p) {
int result = 0, power = p;
while (power <= n) {
result += n / power;
power =power* p;
}
return result;
}
bool isPrime (int n) {
for (int i = 2; i < n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
void get_prime () {
for (int i = 2; i < maxn0; i++) {
if (isPrime(i)) {
primes.push_back(i);
}
}
}
Maybe your prime generation is faulty, but certainly your get_powers implementation is susceptible to int overflow.
int get_powers (int n, int p) {
int result = 0, power = p;
while (power <= n) {
result += n / power;
power =power* p;
}
return result;
}
If int is, as it usually is, a 32-bit wide type, for primes larger than 46341 the computation power = power * p; overflows the first time it is done. That can lead to wrong results, for example
get_powers(10000000, 131071)
returns 52 if the overflow behaviour is wraparound modulo 232, but the correct result would be 76. Now, since m is smaller than 231, this particular one wouldn't hurt, since m cannot be divisible by 131071². But under the wraparound behaviour,
get_powers(1000000, 699733) = -2192
is negative, so for n = 1000000 and m = 2*699733 for example, you would wrongly conclude that n! isn't divisible by m.
To avoid the possible overflow, only divide by p,
int get_powers(int n, int p) {
int result = 0;
n /= p;
do {
result += n;
n /= p;
}while(n > 0);
return result;
}
From the comments:
I edited to add my functions to get primes till constant number "maxn0" – userG 2 hours ago
What value have you chosen for maxn0? – Daniel Fischer 2 hours ago
maxn0 = 10000
That value is too small.
With the primes to 10000, you are only guaranteed to correctly factorise numbers not exceeding 108 (well, since the next prime is 10007, numbers smaller than 10007² = 100140049), but the limit is given as 231, which is much larger.
Whenever a number m is given with two (not necessarily distinct) prime factors larger than 10000, you will not correctly factorise that, and that will usually lead to a wrong answer.
You need all primes ≤ √(231-1), that is all primes < 46340 to obtain the correct factorisation of all admissible m.
EDIT: wrong answer due to a misanderstanding of the question.
9 divides 7! but your algorithm will answer false because get_powers(7, 3) == 0 and 3 is a factor of 9.
It is not your implementation that is wrong but your algorithm.
for( a=1; a <= 25; a++){
num1 = m[a];
for( b=1; b <= 25; b++){
num2 = m[b];
for( c=1; c <= 25; c++){
num3 = m[c];
for( d=1; d <= 25; d++){
num4 = m[d];
for( e=1; e <= 25; e++){
num5 = m[e];
for( f=1; f <= 25; f++){
num6 = m[f];
for( g=1; g <= 25; g++){
num7 = m[g];
for( h=1; h <= 25; h++){
num8 = m[h];
for( i=1; i <= 25; i++){
num = num1*100000000 + num2*10000000 +
num3* 1000000 + num4* 100000 +
num5* 10000 + num6* 1000 +
num7* 100 + num8* 10 + m[i];
check_prime = 1;
for ( y=2; y <= num/2; y++)
{
if ( num % y == 0 )
check_prime = 0;
}
if ( check_prime != 0 )
{
array[x++] = num;
}
num = 0;
}}}}}}}}}
The above code takes a hell lot of time to finish executing.. In fact it doesn't even finish executing, What can i do to optimize the loop and speed up the execution?? I am newbie to cpp.
Replace this code with code using a sensible algorithm, such as the Sieve of Eratosthenes. The most important "optimization" is choosing the right algorithm in the first place.
If your algorithm for sorting numbers is to swap them randomly until they're in order, it doesn't matter how much you optimize the selecting of the random entries, swapping them, or checking if they're in order. A bad algorithm will mean bad performance regardless.
You're checking 259 = 3,814,697,265,625 numbers whether they're prime. That's a lot of prime tests and will always take long. Even in the best case (for performance) when all array entries (in m) are 0 (never mind that the test considers 0 a prime), so that the trial division loop never runs, it will take hours to run. When all entries of m are positive, the code as is will run for hundreds or thousands of years, since then each number will be trial-divided by more than 50,000,000 numbers.
Looking at the prime check,
check_prime = 1;
for ( y = 2; y <= num/2; y++)
{
if ( num % y == 0 )
check_prime = 0;
}
the first glaring inefficiency is that the loop continues even after a divisor has been found and the compositeness of num established. Break out of the loop as soon as you know the outcome.
check_prime = 1;
for ( y = 2; y <= num/2; y++)
{
if ( num % y == 0 )
{
check_prime = 0;
break;
}
}
In the unfortunate case that all numbers you test are prime, that won't change a thing, but if all (or almost all, for sufficiently large values of almost) the numbers are composite, it will cut the running time by a factor of at least 5000.
The next thing is that you divide up to num/2. That is not necessary. Why do you stop at num/2, and not at num - 1? Well, because you figured out that the largest proper divisor of num cannot be larger than num/2 because if (num >) k > num/2, then 2*k > num and num is not a multiple of k.
That's good, not everybody sees that.
But you can pursue that train of thought further. If num/2 is a divisor of num, that means num = 2*(num/2) (using integer division, with the exception of num = 3). But then num is even, and its compositeness was already determined by the division by 2, so the division by num/2 will never be tried if it succeeds.
So what's the next possible candidate for the largest divisor that needs to be considered? num/3 of course. But if that's a divisor of num, then num = 3*(num/3) (unless num < 9) and the division by 3 has already settled the question.
Going on, if k < √num and num/k is a divisor of num, then num = k*(num/k) and we see that num has a smaller divisor, namely k (possibly even smaller ones).
So the smallest nontrivial divisor of num is less than or equal to √num. Thus the loop needs only run for y <= √num, or y*y <= num. If no divisor has been found in that range, num is prime.
Now the question arises whether to loop
for(y = 2; y*y <= num; ++y)
or
root = floor(sqrt(num));
for(y = 2; y <= root; ++y)
The first needs one multiplication for the loop condition in each iteration, the second one computation of the square root outside the loop.
Which is faster?
That depends on the average size of num and whether many are prime or not (more precisely, on the average size of the smallest prime divisor). Computing a square root takes much longer than a multiplication, to compensate that cost, the loop must run for many iterations (on average) - whether "many" means more than 20, more than 100 or more than 1000, say, depends. With num larger than 10^8, as is probably the case here, probably computing the square root is the better choice.
Now we have bounded the number of iterations of the trial division loop to √num whether num is composite or prime and reduced the running time by a factor of at least 5000 (assuming that all m[index] > 0, so that always num >= 10^8) regardless of how many primes are among the tested numbers. If most values num takes are composites with small prime factors, the reduction factor is much larger, to the extent that normally, the running time is almost completely used for testing primes.
Further improvement can be obtained by reducing the number of divisor candidates. If num is divisible by 4, 6, 8, ..., then it is also divisible by 2, so num % y never yields 0 for even y > 2. That means all these divisions are superfluous. By special casing 2 and incrementing the divisor candidate in steps of 2,
if (num % 2 == 0)
{
check_prime = 0;
} else {
root = floor(sqrt(num));
for(y = 3; y <= root; y += 2)
{
if (num % y == 0)
{
check_prime = 0;
break;
}
}
}
the number of divisions to perform and the running time is roughly halved (assuming enough bad cases that the work for even numbers is negligible).
Now, whenever y is a multiple of 3 (other than 3 itself), num % y will only be computed when num is not a multiple of 3, so these divisions are also superfluous. You can eliminate them by also special-casing 3 and letting y run through only the odd numbers that are not divisible by 3 (start with y = 5, increment by 2 and 4 alternatingly). That chops off roughly a third of the remaining work (if enough bad cases are present).
Continuing that elimination process, we need only divide num by the primes not exceeding √num to find whether it's prime or not.
So usually it would be a good idea to find the primes not exceeding the square root of the largest num you'll check, store them in an array and loop
root = floor(sqrt(num));
for(k = 0, y = primes[0]; k < prime_count && (y = primes[k]) <= root; ++k)
{
if (num % y == 0)
{
check_prime = 0;
break;
}
}
Unless the largest value num can take is small enough, if, for example, you'll always have num < 2^31, then you should find the primes to that limit in a bit-sieve so that you can look up whether num is prime in constant time (a sieve of 2^31 bits takes 256 MB, if you only have flags for the odd numbers [needs special-casing to check whether num is even], you only need 128 MB to check the primality of numbers < 2^31 in constant time, further reduction of required space for the sieve is possible).
So far for the prime test itself.
If the m array contains numbers divisible by 2 or by 5, it may be worthwhile to reorder the loops, have the loop for i the outermost, and skip the inner loops if m[i] is divisible by 2 or by 5 - all the other numbers are multiplied by powers of 10 before adding, so then num would be a multiple of 2 resp. 5 and not prime.
But, despite all that, it will still take long to run the code. Nine nested loops reek of a wrong design.
What is it that you try to do? Maybe we can help finding the correct design.
We can eliminate a lot of redundant calculations by calculating each part of the number as it becomes available. This also shows the trial division test for primality on 2-3 wheel up to the square root of a number:
// array m[] is assumed sorted in descending order NB!
// a macro to skip over the duplicate digits
#define I(x) while( x<25 && m[x+1]==m[x] ) ++x;
for( a=1; a <= 25; a++) {
num1 = m[a]*100000000;
for( b=1; b <= 25; b++) if (b != a) {
num2 = num1 + m[b]*10000000;
for( c=1; c <= 25; c++) if (c != b && c != a) {
num3 = num2 + m[c]*1000000;
for( d=1; d <= 25; d++) if (d!=c && d!=b && d!=a) {
num4 = num3 + m[d]*100000;
for( e=1; e <= 25; e++) if (e!=d && e!=c && e!=b && e!=a) {
num5 = num4 + m[e]*10000;
for( f=1; f <= 25; f++) if (f!=e&&f!=d&&f!=c&&f!=b&&f!=a) {
num6 = num5 + m[f]*1000;
limit = floor( sqrt( num6+1000 )); ///
for( g=1; g <= 25; g++) if (g!=f&&g!=e&&g!=d&&g!=c&&g!=b&&g!=a) {
num7 = num6 + m[g]*100;
for( h=1; h <= 25; h++) if (h!=g&&h!=f&&h!=e&&h!=d&&h!=c&&h!=b&&h!=a) {
num8 = num7 + m[h]*10;
for( i=1; i <= 25; i++) if (i!=h&&i!=g&&i!=f&&i!=e&&i!=d
&&i!=c&&i!=b&&i!=a) {
num = num8 + m[i];
if( num % 2 /= 0 && num % 3 /= 0 ) {
is_prime = 1;
for ( y=5; y <= limit; y+=6) {
if ( num % y == 0 ) { is_prime = 0; break; }
if ( num % (y+2) == 0 ) { is_prime = 0; break; }
}
if ( is_prime ) { return( num ); } // largest prime found
}I(i)}I(h)}I(g)}I(f)}I(e)}I(d)}I(c)}I(b)}I(a)}
This code also eliminates the duplicate indices. As you've indicated in the comments, you pick your numbers out of a 5x5 grid. That means that you must use all different indices. This will bring down the count of numbers to test from 25^9 = 3,814,697,265,625 to 25*24*23*...*17 = 741,354,768,000.
Since you've now indicated that all entries in the m[] array are less than 10, there certain to be duplicates, which need to be skipped when searching. As Daniel points out, searching from the top, the first found prime will be the biggest. This is achieved by pre-sorting the m[] array in descending order.