Relative prime numbers
Two integers a and b are relatively prime if and only if there are no integers:
x > 1, y > 0, z > 0 such that a = xy and b = xz.
I wrote a program that determines how many positive integers less than n
are relatively prime to n
. But my program works too slowly because the number is sometimes too big.
My program should work for n <= 1000000000
.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
long long int n;
int cntr = 0, cntr2 = 0;
cin >> n;
if (!n) return 0;
vector <int> num;
for (int i = 2; i < n; i++)
{
if (n % i != 0)
{
if (num.size()>0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
cntr2 = 0;
}
else
cntr++;
}
else
num.push_back(i);
}
cout << cntr + 1 << endl;
}
c++ performance primes
add a comment |
Two integers a and b are relatively prime if and only if there are no integers:
x > 1, y > 0, z > 0 such that a = xy and b = xz.
I wrote a program that determines how many positive integers less than n
are relatively prime to n
. But my program works too slowly because the number is sometimes too big.
My program should work for n <= 1000000000
.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
long long int n;
int cntr = 0, cntr2 = 0;
cin >> n;
if (!n) return 0;
vector <int> num;
for (int i = 2; i < n; i++)
{
if (n % i != 0)
{
if (num.size()>0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
cntr2 = 0;
}
else
cntr++;
}
else
num.push_back(i);
}
cout << cntr + 1 << endl;
}
c++ performance primes
add a comment |
Two integers a and b are relatively prime if and only if there are no integers:
x > 1, y > 0, z > 0 such that a = xy and b = xz.
I wrote a program that determines how many positive integers less than n
are relatively prime to n
. But my program works too slowly because the number is sometimes too big.
My program should work for n <= 1000000000
.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
long long int n;
int cntr = 0, cntr2 = 0;
cin >> n;
if (!n) return 0;
vector <int> num;
for (int i = 2; i < n; i++)
{
if (n % i != 0)
{
if (num.size()>0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
cntr2 = 0;
}
else
cntr++;
}
else
num.push_back(i);
}
cout << cntr + 1 << endl;
}
c++ performance primes
Two integers a and b are relatively prime if and only if there are no integers:
x > 1, y > 0, z > 0 such that a = xy and b = xz.
I wrote a program that determines how many positive integers less than n
are relatively prime to n
. But my program works too slowly because the number is sometimes too big.
My program should work for n <= 1000000000
.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
long long int n;
int cntr = 0, cntr2 = 0;
cin >> n;
if (!n) return 0;
vector <int> num;
for (int i = 2; i < n; i++)
{
if (n % i != 0)
{
if (num.size()>0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
cntr2 = 0;
}
else
cntr++;
}
else
num.push_back(i);
}
cout << cntr + 1 << endl;
}
c++ performance primes
c++ performance primes
edited Jan 12 '14 at 23:34
Jamal♦
30.3k11116226
30.3k11116226
asked Jan 12 '14 at 23:31
DanialV
1612
1612
add a comment |
add a comment |
5 Answers
5
active
oldest
votes
In order to determine whether two numbers are co-prime (relatively prime), you can check whether their gcd (greatest common divisor) is greater than 1.
The gcd can be calculated by Euclid's algorithm:
unsigned int gcd (unsigned int a, unsigned int b)
{
unsigned int x;
while (b)
{
x = a % b;
a = b;
b = x;
}
return a;
}
if gcd(x,y) > 1: the numbers are not co-prime.
If the code is supposed to run on a platform with slow integer division, you can use the so called binary gcd instead.
Original sultion might be a bit better because it takes into account the fact that we need to find set of co-primes rather than check one particular pair.
– ony
Jan 13 '14 at 9:19
add a comment |
Your code can be simplified by eliminating a special case. This…
if (n % i != 0)
{
if (num.size()>0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
cntr2 = 0;
}
else
cntr++;
}
… can be written as:
if (n % i != 0)
{
int cntr2 = 0;
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
}
Furthermore, you could eliminate cntr2
. Breaking from the loop earlier saves work and should improve performance.
if (n % i != 0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] == 0)
{
cntr--;
break;
}
}
cntr++;
}
Didn't you've lost populatingnum
vector?
– ony
Jan 13 '14 at 8:15
@ony I took the wrong excerpt. Thanks!
– 200_success
Jan 13 '14 at 8:27
add a comment |
Suggestions from @200_success will bring you speedup like from ~28.1s to ~11.8s (gcc 4.8.2 with -O3).
Replacing all with gcd
as suggested @EOF will give you ~11.4s and will save some memory.
Overall idea is somewhat correct. You collect factors of n
and check that there is no factors within other numbers (that are not already factors of n
).
But I guess you can improve solution by factoring with primes and avoid populating num
with numbers like 4, 6, 8, 9 etc. That brings time to ~1.3s.
for (int i = 2; i < n; i++)
{
if (n % i == 0)
{
bool foundFactor = false;
for (int j = 0; j < num.size(); ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor) num.push_back(i);
continue;
}
bool foundFactor = false;
for (int j = 0; j < num.size(); ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor)
cntr++;
}
For your n = 1000000000
I've got ~13.6s
Note that there is a linear relation beetween numbers of co-primes in 1000000000 and 1000. That's because the only difference between them is (2*5)**k
. That leads us to another optimization based on the wheel factorization:
long long wheel = 1;
// factorization of n
for (long long i = 2, m = n; i <= m; i++)
{
if (m % i == 0)
{
num.push_back(i);
wheel *= i; // re-size wheel
// remove powers of i from m
do { m /= i; } while (m % i == 0);
}
}
for (int i = 2; i < wheel; i++)
{
if (n % i == 0)
{
continue;
}
bool foundFactor = false;
for (int j = 0; j < num.size() && num[j] < i; ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor)
cntr++;
}
cout << cntr+1 << endl;
cout << (cntr+1)*n/wheel << endl;
That gives ~0s for almost any 10**k
P.S. It sound pretty much as Project Euler problem I've met once. I used a bit different approach. I already had a pretty good framework for working with primes and I just simply generated all numbers out of primes that have no factors of n
initially. I.e. built up sequence of combinations 3**k * 7**k ...
until they've reached n
.
add a comment |
I don't know if you still need this, since it is a very old question. I wrote it for anybody else who might be looking for the answer.
This counts every N's "relatively prime number" (less then N). It is called Eulers' totient function.
#include <cstdio>
typedef long long lld;
lld f(lld num)
{
lld ans = num;
for (lld i = 2; i*i <= num; i++)
{
if (num%i==0)
{
while (num%i==0) num /= i;
ans -= ans / i;
}
}
if (num > 1)
ans -= ans / num;
return ans;
}
int main()
{
lld N;
scanf("%lld", &N);
printf("%lld", f(N));
}
Euler's totient function
– Gs_
Jun 7 '17 at 13:16
2
This is basically a code dump answer (even after moving the explanatory text to the top). Every answer must make at least one insightful observation about the code in the question and not just offer an alternative implementation without at least explaining what it does better or how. See the help-center for more information.
– Graipher
Jun 7 '17 at 13:36
add a comment |
Gs_'s answer starts off by essentially finding all the prime factors of n
. If you're going to do that, then you might as well use the following well-known formula that calculates the Euler function from the prime factorisation:
phi(p1 ^ a1 * ... * pk ^ ak) =
(p1 ^ a1 - p1 ^ (a1 - 1))
* ...
* (pk ^ ak - pk ^ (ak - 1))
The code would look something like this:
long long phi = 1;
// factorization of n
for (long long i = 2, m = n; m > 1; i++)
{
// Now phi(n/m) == phi
if (m % i == 0)
{
// i is the smallest prime factor of m, and is not a factor of n/m
m /= i;
phi *= (i - 1);
while (m % i == 0) {
m /= i;
phi *= i;
}
}
}
return phi;
What'swheel
?
– 200_success
Jan 13 '14 at 12:07
@200_success That was in ony's code. I forgot to delete it. It's removed now. Thanks.
– David Knipe
Jan 13 '14 at 12:34
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f39109%2frelative-prime-numbers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
In order to determine whether two numbers are co-prime (relatively prime), you can check whether their gcd (greatest common divisor) is greater than 1.
The gcd can be calculated by Euclid's algorithm:
unsigned int gcd (unsigned int a, unsigned int b)
{
unsigned int x;
while (b)
{
x = a % b;
a = b;
b = x;
}
return a;
}
if gcd(x,y) > 1: the numbers are not co-prime.
If the code is supposed to run on a platform with slow integer division, you can use the so called binary gcd instead.
Original sultion might be a bit better because it takes into account the fact that we need to find set of co-primes rather than check one particular pair.
– ony
Jan 13 '14 at 9:19
add a comment |
In order to determine whether two numbers are co-prime (relatively prime), you can check whether their gcd (greatest common divisor) is greater than 1.
The gcd can be calculated by Euclid's algorithm:
unsigned int gcd (unsigned int a, unsigned int b)
{
unsigned int x;
while (b)
{
x = a % b;
a = b;
b = x;
}
return a;
}
if gcd(x,y) > 1: the numbers are not co-prime.
If the code is supposed to run on a platform with slow integer division, you can use the so called binary gcd instead.
Original sultion might be a bit better because it takes into account the fact that we need to find set of co-primes rather than check one particular pair.
– ony
Jan 13 '14 at 9:19
add a comment |
In order to determine whether two numbers are co-prime (relatively prime), you can check whether their gcd (greatest common divisor) is greater than 1.
The gcd can be calculated by Euclid's algorithm:
unsigned int gcd (unsigned int a, unsigned int b)
{
unsigned int x;
while (b)
{
x = a % b;
a = b;
b = x;
}
return a;
}
if gcd(x,y) > 1: the numbers are not co-prime.
If the code is supposed to run on a platform with slow integer division, you can use the so called binary gcd instead.
In order to determine whether two numbers are co-prime (relatively prime), you can check whether their gcd (greatest common divisor) is greater than 1.
The gcd can be calculated by Euclid's algorithm:
unsigned int gcd (unsigned int a, unsigned int b)
{
unsigned int x;
while (b)
{
x = a % b;
a = b;
b = x;
}
return a;
}
if gcd(x,y) > 1: the numbers are not co-prime.
If the code is supposed to run on a platform with slow integer division, you can use the so called binary gcd instead.
edited Jan 13 '14 at 1:36
izabera
1734
1734
answered Jan 12 '14 at 23:54
EOF
31117
31117
Original sultion might be a bit better because it takes into account the fact that we need to find set of co-primes rather than check one particular pair.
– ony
Jan 13 '14 at 9:19
add a comment |
Original sultion might be a bit better because it takes into account the fact that we need to find set of co-primes rather than check one particular pair.
– ony
Jan 13 '14 at 9:19
Original sultion might be a bit better because it takes into account the fact that we need to find set of co-primes rather than check one particular pair.
– ony
Jan 13 '14 at 9:19
Original sultion might be a bit better because it takes into account the fact that we need to find set of co-primes rather than check one particular pair.
– ony
Jan 13 '14 at 9:19
add a comment |
Your code can be simplified by eliminating a special case. This…
if (n % i != 0)
{
if (num.size()>0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
cntr2 = 0;
}
else
cntr++;
}
… can be written as:
if (n % i != 0)
{
int cntr2 = 0;
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
}
Furthermore, you could eliminate cntr2
. Breaking from the loop earlier saves work and should improve performance.
if (n % i != 0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] == 0)
{
cntr--;
break;
}
}
cntr++;
}
Didn't you've lost populatingnum
vector?
– ony
Jan 13 '14 at 8:15
@ony I took the wrong excerpt. Thanks!
– 200_success
Jan 13 '14 at 8:27
add a comment |
Your code can be simplified by eliminating a special case. This…
if (n % i != 0)
{
if (num.size()>0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
cntr2 = 0;
}
else
cntr++;
}
… can be written as:
if (n % i != 0)
{
int cntr2 = 0;
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
}
Furthermore, you could eliminate cntr2
. Breaking from the loop earlier saves work and should improve performance.
if (n % i != 0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] == 0)
{
cntr--;
break;
}
}
cntr++;
}
Didn't you've lost populatingnum
vector?
– ony
Jan 13 '14 at 8:15
@ony I took the wrong excerpt. Thanks!
– 200_success
Jan 13 '14 at 8:27
add a comment |
Your code can be simplified by eliminating a special case. This…
if (n % i != 0)
{
if (num.size()>0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
cntr2 = 0;
}
else
cntr++;
}
… can be written as:
if (n % i != 0)
{
int cntr2 = 0;
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
}
Furthermore, you could eliminate cntr2
. Breaking from the loop earlier saves work and should improve performance.
if (n % i != 0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] == 0)
{
cntr--;
break;
}
}
cntr++;
}
Your code can be simplified by eliminating a special case. This…
if (n % i != 0)
{
if (num.size()>0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
cntr2 = 0;
}
else
cntr++;
}
… can be written as:
if (n % i != 0)
{
int cntr2 = 0;
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] != 0)
cntr2++;
}
if (cntr2 == num.size())
cntr++;
}
Furthermore, you could eliminate cntr2
. Breaking from the loop earlier saves work and should improve performance.
if (n % i != 0)
{
for (int j = 0; j < num.size(); j++)
{
if (i % num[j] == 0)
{
cntr--;
break;
}
}
cntr++;
}
edited Jan 13 '14 at 8:27
answered Jan 13 '14 at 2:23
200_success
128k15152413
128k15152413
Didn't you've lost populatingnum
vector?
– ony
Jan 13 '14 at 8:15
@ony I took the wrong excerpt. Thanks!
– 200_success
Jan 13 '14 at 8:27
add a comment |
Didn't you've lost populatingnum
vector?
– ony
Jan 13 '14 at 8:15
@ony I took the wrong excerpt. Thanks!
– 200_success
Jan 13 '14 at 8:27
Didn't you've lost populating
num
vector?– ony
Jan 13 '14 at 8:15
Didn't you've lost populating
num
vector?– ony
Jan 13 '14 at 8:15
@ony I took the wrong excerpt. Thanks!
– 200_success
Jan 13 '14 at 8:27
@ony I took the wrong excerpt. Thanks!
– 200_success
Jan 13 '14 at 8:27
add a comment |
Suggestions from @200_success will bring you speedup like from ~28.1s to ~11.8s (gcc 4.8.2 with -O3).
Replacing all with gcd
as suggested @EOF will give you ~11.4s and will save some memory.
Overall idea is somewhat correct. You collect factors of n
and check that there is no factors within other numbers (that are not already factors of n
).
But I guess you can improve solution by factoring with primes and avoid populating num
with numbers like 4, 6, 8, 9 etc. That brings time to ~1.3s.
for (int i = 2; i < n; i++)
{
if (n % i == 0)
{
bool foundFactor = false;
for (int j = 0; j < num.size(); ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor) num.push_back(i);
continue;
}
bool foundFactor = false;
for (int j = 0; j < num.size(); ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor)
cntr++;
}
For your n = 1000000000
I've got ~13.6s
Note that there is a linear relation beetween numbers of co-primes in 1000000000 and 1000. That's because the only difference between them is (2*5)**k
. That leads us to another optimization based on the wheel factorization:
long long wheel = 1;
// factorization of n
for (long long i = 2, m = n; i <= m; i++)
{
if (m % i == 0)
{
num.push_back(i);
wheel *= i; // re-size wheel
// remove powers of i from m
do { m /= i; } while (m % i == 0);
}
}
for (int i = 2; i < wheel; i++)
{
if (n % i == 0)
{
continue;
}
bool foundFactor = false;
for (int j = 0; j < num.size() && num[j] < i; ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor)
cntr++;
}
cout << cntr+1 << endl;
cout << (cntr+1)*n/wheel << endl;
That gives ~0s for almost any 10**k
P.S. It sound pretty much as Project Euler problem I've met once. I used a bit different approach. I already had a pretty good framework for working with primes and I just simply generated all numbers out of primes that have no factors of n
initially. I.e. built up sequence of combinations 3**k * 7**k ...
until they've reached n
.
add a comment |
Suggestions from @200_success will bring you speedup like from ~28.1s to ~11.8s (gcc 4.8.2 with -O3).
Replacing all with gcd
as suggested @EOF will give you ~11.4s and will save some memory.
Overall idea is somewhat correct. You collect factors of n
and check that there is no factors within other numbers (that are not already factors of n
).
But I guess you can improve solution by factoring with primes and avoid populating num
with numbers like 4, 6, 8, 9 etc. That brings time to ~1.3s.
for (int i = 2; i < n; i++)
{
if (n % i == 0)
{
bool foundFactor = false;
for (int j = 0; j < num.size(); ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor) num.push_back(i);
continue;
}
bool foundFactor = false;
for (int j = 0; j < num.size(); ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor)
cntr++;
}
For your n = 1000000000
I've got ~13.6s
Note that there is a linear relation beetween numbers of co-primes in 1000000000 and 1000. That's because the only difference between them is (2*5)**k
. That leads us to another optimization based on the wheel factorization:
long long wheel = 1;
// factorization of n
for (long long i = 2, m = n; i <= m; i++)
{
if (m % i == 0)
{
num.push_back(i);
wheel *= i; // re-size wheel
// remove powers of i from m
do { m /= i; } while (m % i == 0);
}
}
for (int i = 2; i < wheel; i++)
{
if (n % i == 0)
{
continue;
}
bool foundFactor = false;
for (int j = 0; j < num.size() && num[j] < i; ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor)
cntr++;
}
cout << cntr+1 << endl;
cout << (cntr+1)*n/wheel << endl;
That gives ~0s for almost any 10**k
P.S. It sound pretty much as Project Euler problem I've met once. I used a bit different approach. I already had a pretty good framework for working with primes and I just simply generated all numbers out of primes that have no factors of n
initially. I.e. built up sequence of combinations 3**k * 7**k ...
until they've reached n
.
add a comment |
Suggestions from @200_success will bring you speedup like from ~28.1s to ~11.8s (gcc 4.8.2 with -O3).
Replacing all with gcd
as suggested @EOF will give you ~11.4s and will save some memory.
Overall idea is somewhat correct. You collect factors of n
and check that there is no factors within other numbers (that are not already factors of n
).
But I guess you can improve solution by factoring with primes and avoid populating num
with numbers like 4, 6, 8, 9 etc. That brings time to ~1.3s.
for (int i = 2; i < n; i++)
{
if (n % i == 0)
{
bool foundFactor = false;
for (int j = 0; j < num.size(); ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor) num.push_back(i);
continue;
}
bool foundFactor = false;
for (int j = 0; j < num.size(); ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor)
cntr++;
}
For your n = 1000000000
I've got ~13.6s
Note that there is a linear relation beetween numbers of co-primes in 1000000000 and 1000. That's because the only difference between them is (2*5)**k
. That leads us to another optimization based on the wheel factorization:
long long wheel = 1;
// factorization of n
for (long long i = 2, m = n; i <= m; i++)
{
if (m % i == 0)
{
num.push_back(i);
wheel *= i; // re-size wheel
// remove powers of i from m
do { m /= i; } while (m % i == 0);
}
}
for (int i = 2; i < wheel; i++)
{
if (n % i == 0)
{
continue;
}
bool foundFactor = false;
for (int j = 0; j < num.size() && num[j] < i; ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor)
cntr++;
}
cout << cntr+1 << endl;
cout << (cntr+1)*n/wheel << endl;
That gives ~0s for almost any 10**k
P.S. It sound pretty much as Project Euler problem I've met once. I used a bit different approach. I already had a pretty good framework for working with primes and I just simply generated all numbers out of primes that have no factors of n
initially. I.e. built up sequence of combinations 3**k * 7**k ...
until they've reached n
.
Suggestions from @200_success will bring you speedup like from ~28.1s to ~11.8s (gcc 4.8.2 with -O3).
Replacing all with gcd
as suggested @EOF will give you ~11.4s and will save some memory.
Overall idea is somewhat correct. You collect factors of n
and check that there is no factors within other numbers (that are not already factors of n
).
But I guess you can improve solution by factoring with primes and avoid populating num
with numbers like 4, 6, 8, 9 etc. That brings time to ~1.3s.
for (int i = 2; i < n; i++)
{
if (n % i == 0)
{
bool foundFactor = false;
for (int j = 0; j < num.size(); ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor) num.push_back(i);
continue;
}
bool foundFactor = false;
for (int j = 0; j < num.size(); ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor)
cntr++;
}
For your n = 1000000000
I've got ~13.6s
Note that there is a linear relation beetween numbers of co-primes in 1000000000 and 1000. That's because the only difference between them is (2*5)**k
. That leads us to another optimization based on the wheel factorization:
long long wheel = 1;
// factorization of n
for (long long i = 2, m = n; i <= m; i++)
{
if (m % i == 0)
{
num.push_back(i);
wheel *= i; // re-size wheel
// remove powers of i from m
do { m /= i; } while (m % i == 0);
}
}
for (int i = 2; i < wheel; i++)
{
if (n % i == 0)
{
continue;
}
bool foundFactor = false;
for (int j = 0; j < num.size() && num[j] < i; ++j)
{
if (i % num[j] == 0)
{
foundFactor = true;
break;
}
}
if (!foundFactor)
cntr++;
}
cout << cntr+1 << endl;
cout << (cntr+1)*n/wheel << endl;
That gives ~0s for almost any 10**k
P.S. It sound pretty much as Project Euler problem I've met once. I used a bit different approach. I already had a pretty good framework for working with primes and I just simply generated all numbers out of primes that have no factors of n
initially. I.e. built up sequence of combinations 3**k * 7**k ...
until they've reached n
.
edited Jan 13 '14 at 9:31
answered Jan 13 '14 at 8:56
ony
61135
61135
add a comment |
add a comment |
I don't know if you still need this, since it is a very old question. I wrote it for anybody else who might be looking for the answer.
This counts every N's "relatively prime number" (less then N). It is called Eulers' totient function.
#include <cstdio>
typedef long long lld;
lld f(lld num)
{
lld ans = num;
for (lld i = 2; i*i <= num; i++)
{
if (num%i==0)
{
while (num%i==0) num /= i;
ans -= ans / i;
}
}
if (num > 1)
ans -= ans / num;
return ans;
}
int main()
{
lld N;
scanf("%lld", &N);
printf("%lld", f(N));
}
Euler's totient function
– Gs_
Jun 7 '17 at 13:16
2
This is basically a code dump answer (even after moving the explanatory text to the top). Every answer must make at least one insightful observation about the code in the question and not just offer an alternative implementation without at least explaining what it does better or how. See the help-center for more information.
– Graipher
Jun 7 '17 at 13:36
add a comment |
I don't know if you still need this, since it is a very old question. I wrote it for anybody else who might be looking for the answer.
This counts every N's "relatively prime number" (less then N). It is called Eulers' totient function.
#include <cstdio>
typedef long long lld;
lld f(lld num)
{
lld ans = num;
for (lld i = 2; i*i <= num; i++)
{
if (num%i==0)
{
while (num%i==0) num /= i;
ans -= ans / i;
}
}
if (num > 1)
ans -= ans / num;
return ans;
}
int main()
{
lld N;
scanf("%lld", &N);
printf("%lld", f(N));
}
Euler's totient function
– Gs_
Jun 7 '17 at 13:16
2
This is basically a code dump answer (even after moving the explanatory text to the top). Every answer must make at least one insightful observation about the code in the question and not just offer an alternative implementation without at least explaining what it does better or how. See the help-center for more information.
– Graipher
Jun 7 '17 at 13:36
add a comment |
I don't know if you still need this, since it is a very old question. I wrote it for anybody else who might be looking for the answer.
This counts every N's "relatively prime number" (less then N). It is called Eulers' totient function.
#include <cstdio>
typedef long long lld;
lld f(lld num)
{
lld ans = num;
for (lld i = 2; i*i <= num; i++)
{
if (num%i==0)
{
while (num%i==0) num /= i;
ans -= ans / i;
}
}
if (num > 1)
ans -= ans / num;
return ans;
}
int main()
{
lld N;
scanf("%lld", &N);
printf("%lld", f(N));
}
I don't know if you still need this, since it is a very old question. I wrote it for anybody else who might be looking for the answer.
This counts every N's "relatively prime number" (less then N). It is called Eulers' totient function.
#include <cstdio>
typedef long long lld;
lld f(lld num)
{
lld ans = num;
for (lld i = 2; i*i <= num; i++)
{
if (num%i==0)
{
while (num%i==0) num /= i;
ans -= ans / i;
}
}
if (num > 1)
ans -= ans / num;
return ans;
}
int main()
{
lld N;
scanf("%lld", &N);
printf("%lld", f(N));
}
edited Jun 7 '17 at 13:33
Graipher
23.6k53585
23.6k53585
answered Jun 7 '17 at 13:11
Gs_
91
91
Euler's totient function
– Gs_
Jun 7 '17 at 13:16
2
This is basically a code dump answer (even after moving the explanatory text to the top). Every answer must make at least one insightful observation about the code in the question and not just offer an alternative implementation without at least explaining what it does better or how. See the help-center for more information.
– Graipher
Jun 7 '17 at 13:36
add a comment |
Euler's totient function
– Gs_
Jun 7 '17 at 13:16
2
This is basically a code dump answer (even after moving the explanatory text to the top). Every answer must make at least one insightful observation about the code in the question and not just offer an alternative implementation without at least explaining what it does better or how. See the help-center for more information.
– Graipher
Jun 7 '17 at 13:36
Euler's totient function
– Gs_
Jun 7 '17 at 13:16
Euler's totient function
– Gs_
Jun 7 '17 at 13:16
2
2
This is basically a code dump answer (even after moving the explanatory text to the top). Every answer must make at least one insightful observation about the code in the question and not just offer an alternative implementation without at least explaining what it does better or how. See the help-center for more information.
– Graipher
Jun 7 '17 at 13:36
This is basically a code dump answer (even after moving the explanatory text to the top). Every answer must make at least one insightful observation about the code in the question and not just offer an alternative implementation without at least explaining what it does better or how. See the help-center for more information.
– Graipher
Jun 7 '17 at 13:36
add a comment |
Gs_'s answer starts off by essentially finding all the prime factors of n
. If you're going to do that, then you might as well use the following well-known formula that calculates the Euler function from the prime factorisation:
phi(p1 ^ a1 * ... * pk ^ ak) =
(p1 ^ a1 - p1 ^ (a1 - 1))
* ...
* (pk ^ ak - pk ^ (ak - 1))
The code would look something like this:
long long phi = 1;
// factorization of n
for (long long i = 2, m = n; m > 1; i++)
{
// Now phi(n/m) == phi
if (m % i == 0)
{
// i is the smallest prime factor of m, and is not a factor of n/m
m /= i;
phi *= (i - 1);
while (m % i == 0) {
m /= i;
phi *= i;
}
}
}
return phi;
What'swheel
?
– 200_success
Jan 13 '14 at 12:07
@200_success That was in ony's code. I forgot to delete it. It's removed now. Thanks.
– David Knipe
Jan 13 '14 at 12:34
add a comment |
Gs_'s answer starts off by essentially finding all the prime factors of n
. If you're going to do that, then you might as well use the following well-known formula that calculates the Euler function from the prime factorisation:
phi(p1 ^ a1 * ... * pk ^ ak) =
(p1 ^ a1 - p1 ^ (a1 - 1))
* ...
* (pk ^ ak - pk ^ (ak - 1))
The code would look something like this:
long long phi = 1;
// factorization of n
for (long long i = 2, m = n; m > 1; i++)
{
// Now phi(n/m) == phi
if (m % i == 0)
{
// i is the smallest prime factor of m, and is not a factor of n/m
m /= i;
phi *= (i - 1);
while (m % i == 0) {
m /= i;
phi *= i;
}
}
}
return phi;
What'swheel
?
– 200_success
Jan 13 '14 at 12:07
@200_success That was in ony's code. I forgot to delete it. It's removed now. Thanks.
– David Knipe
Jan 13 '14 at 12:34
add a comment |
Gs_'s answer starts off by essentially finding all the prime factors of n
. If you're going to do that, then you might as well use the following well-known formula that calculates the Euler function from the prime factorisation:
phi(p1 ^ a1 * ... * pk ^ ak) =
(p1 ^ a1 - p1 ^ (a1 - 1))
* ...
* (pk ^ ak - pk ^ (ak - 1))
The code would look something like this:
long long phi = 1;
// factorization of n
for (long long i = 2, m = n; m > 1; i++)
{
// Now phi(n/m) == phi
if (m % i == 0)
{
// i is the smallest prime factor of m, and is not a factor of n/m
m /= i;
phi *= (i - 1);
while (m % i == 0) {
m /= i;
phi *= i;
}
}
}
return phi;
Gs_'s answer starts off by essentially finding all the prime factors of n
. If you're going to do that, then you might as well use the following well-known formula that calculates the Euler function from the prime factorisation:
phi(p1 ^ a1 * ... * pk ^ ak) =
(p1 ^ a1 - p1 ^ (a1 - 1))
* ...
* (pk ^ ak - pk ^ (ak - 1))
The code would look something like this:
long long phi = 1;
// factorization of n
for (long long i = 2, m = n; m > 1; i++)
{
// Now phi(n/m) == phi
if (m % i == 0)
{
// i is the smallest prime factor of m, and is not a factor of n/m
m /= i;
phi *= (i - 1);
while (m % i == 0) {
m /= i;
phi *= i;
}
}
}
return phi;
edited Jan 1 at 20:08
answered Jan 13 '14 at 11:22
David Knipe
1764
1764
What'swheel
?
– 200_success
Jan 13 '14 at 12:07
@200_success That was in ony's code. I forgot to delete it. It's removed now. Thanks.
– David Knipe
Jan 13 '14 at 12:34
add a comment |
What'swheel
?
– 200_success
Jan 13 '14 at 12:07
@200_success That was in ony's code. I forgot to delete it. It's removed now. Thanks.
– David Knipe
Jan 13 '14 at 12:34
What's
wheel
?– 200_success
Jan 13 '14 at 12:07
What's
wheel
?– 200_success
Jan 13 '14 at 12:07
@200_success That was in ony's code. I forgot to delete it. It's removed now. Thanks.
– David Knipe
Jan 13 '14 at 12:34
@200_success That was in ony's code. I forgot to delete it. It's removed now. Thanks.
– David Knipe
Jan 13 '14 at 12:34
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f39109%2frelative-prime-numbers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown