First of all, I would clarify that I am new to programming and started with c++ recently. There was a problem related to Legendre's formula in my math textbook and I thought about making a program related to it. It takes a number from user n, and finds the highest power of n which divides n!
It runs fine for a lot of numbers but messes up for a few others and it is completely random. This is a snippet from the code.
#include <iostream>
#include <math.h>
using namespace std;
int prime(int);
int calc(int, int);
int main()
{
int n;
int hpf=2;
cout<<"This program finds highest power x that divides x!"<<endl;
cout << "Enter number : " << endl;
cin>>n;
for(int i=2; i<=n; i++)
{
bool p=prime(i);
if(p==true && n%i==0)
hpf=i;
}
cout<<"The highest prime factor of the number is : "<<hpf<<endl;
int p=calc(hpf, n);
cout<<"The highest power of "<<n<<" that divides "<<n<<"!"<<" is : "<<p;
return 0;
}
calc(int f, int n)
{
int c=0 , d=1, power=1, i=0;
while(i>=0)
{
int x= pow(f,power+i);
if(i>0 && n%x==0)
d++;
if(x<=n)
{
c+=n/x;
i++;
}
else
break;
}
return c/d;
}
prime(int n)
{
bool isPrime = true;
for(int i = 2; i <= n/2; i++)
{
if (n%i == 0)
{
isPrime = false;
break;
}
}
return isPrime;
}
I pass the highest prime factor of n and the number n itself to int calc(int, int).
Now here is the problem:
when I input n=9, I get
Enter number :
9
The highest prime factor of the number is : 3
The highest power of 9 that divides 9! is : 2
on the other hand, if I input 25, I get
Enter number :
25
The highest prime factor of the number is : 5
The highest power of 25 that divides 25! is : 6
This is clearly wrong, the highest power should be 3.
It also works for bigger numbers accurately, but not all.
PS: I use codeblocks.
I'm not sure why exactly it works for 9 and not for 25(your program seems fine, but you probably have a problem when you calculate d or something), although both are squares of primes and your code seems to take care of that, but I do know why it doesn't work with number like 12. This happens because your code only looks at the highest prime factor and ignores the others. This will give you the true result when the other prime factors appear less frequently then the biggest one, but in all other cases this assumption leads to wrong results, because the highest is then also limited by smaller primes. So a correct solution has to take care of all prime factors.
For that you first need to factor the number(getting the prime factors and their power!). You can just google that if you are unsure how to do that. I don't want to include it here because then the answer would get to long.
Then you need to find how often the number is present in the factorial.
As you already know(at least you used it in your code) you can count by summing up the occurence as a factor of each power of the prime in every factor of the factorial which can be done through division like this:
n/p¹ + n/p² + n/p³ + n/p⁴ + …
That can be put into a simple function(using a simple self-made power calculation):
int occurenceInFaculty(int factor, int faculty) {
int sum = 0;
for(int power = factor; power <= faculty; power *= factor) { // Go through all powers
sum += faculty/power;
}
return sum;
}
Now you can calculate the occurrence for each of the prime factors of your number and if you divide by the power of that prime factor in the factorization you get an upper limit for the highest power.
Then all that's left to do is take the minimum over all prime factors and you are done.
Assuming one possible way of storing the prime factorization here is what the resulting code could look like:
Somewhere in the beginning of your code:
typedef struct {
int prime;
int power;
} PrimeFactor;
Assuming a prime factorization method like this:
PrimeFactor* factorization(int number, int* factors) {
// Factorize here. Return a pointer to an array of PrimeFactors and set the pointer factors to the arrays length.
}
And then the calculation part:
int number = 25; // Put your number here.
int length = 0;
PrimeFactor* factors = factorization(25, &length);
int min = number; // Some reasonable upper border because n! < n^n
for(int i = 0; i < length; i++) {
if(occurenceInFaculty(factors[i].prime, number)/factors[i].power < min)
min = occurenceInFaculty(factors[i].prime, number)/factors[i].power;
}
This program also gets 25 right!
Related
This question already has answers here:
Sieve of Eratosthenes algorithm
(14 answers)
Closed 3 years ago.
The Prime Generator requires prime numbers between a certain range.
Input :
The input begins with the number t of test cases in a single line (t<=10). In each of the next t lines there are two numbers m and n
(1 <= m <= n <= 1000000000, n-m<=100000) separated by a space.
Output :
For every test case print all prime numbers p such that m <= p <= n, one number per line, test cases separated by an empty line.
My program runs perfectly with this solution but the time limit is exceeded and it isn't accepted as a solution.
I've replaced cin and cout with scanf and printf.
I've replaced for loops with while loops and what not. What other measures can I take to speed up my solution?
#include<iostream>
int prime(unsigned long int p)
{
int f=1,i=2;
while(i<=p/2)
{
if(p%i==0)
{ f=0;
break;
}
++i;
}
if(f==1)
{ printf("%d \n",p);
}
return 0;
}
int main()
{
int t, i=0;
unsigned long int m,n,j;
scanf("%d",&t);
while(i<t)
{
scanf("%lu%lu",&m,&n);
for(j=m;j<=n;++j)
{
if(j!=1&&j!=0)
prime(j);
}
printf("\n");
++i;
}
return 0;
}
Your code is inefficient because you’re using a slow algorithm to find primes. Changing a for loop to a while loop probably won’t speed up the code, but changing to a better algorithm will.
A faster algorithm:
There’s a really simple algorithm called the Sieve of Eratosthenes. We start out by making an array of bools. Mark all of them true. This array will let us keep track of which numbers are and aren’t prime. We’re gonna cross out the ones we know aren’t prime (by setting them to false).
Cross out 0 and 1 from the array
Starting with 4, cross out all numbers that are multiples of 2
Starting with 6, cross out all numbers that are multiples of 3
Starting with 10, cross out all multiples of 5
Starting with 14, cross out all multiples of 7
(Continue this process)
Example:
// takes a reference to a vector of bools
// a vector is a resizable array
void cross_out_multiples(std::vector<bool>& primes, int num) {
for(int i = num * 2; i < primes.size(); i += num) {
primes[i] = false;
}
}
std::vector<int> findPrimes(int max) {
std::vector<bool> primes(max); // create array with max elements
for(int i = 0; i < max; ++i) {
primes[i] = true;
}
// 0 and 1 aren’t prime, so we mark them false
primes[0] = false;
primes[1] = false;
// here we mark multiples of n false
for(int n = 2; n < max; n++) {
// if a number isn’t prime, we can skip it
if(not primes[n]) {
continue;
}
// if n squared is bigger than max, we already
// crossed out all multiples of n smaller than max
// so we don’t have any more work to do
if(n * n > max) {
break;
}
// now we just cross out multiples of n
cross_out_multiples(primes, n);
}
// now, take the numbers that are prime:
std::vector<int> listOfPrimes;
for(int i = 0; i < max; i++) {
// if a number is prime, add it to the list
if(primes[i]) {
listOfPrimes.push_back(i);
}
}
return listOfPrimes;
}I
Your code is correct, but (very) inefficient. The online judge not only requires correctness, but also efficiency.
The simple scanning algorithm of yours can be immediately made faster by two simple measures:
only test odd divisors
only test divisors up to sqrt(p) (which for large p is much smaller than p/2)
But ultimately learn about the sieve of Eratosthenes.
#include <iostream>
using namespace std;
int ifprime(long long int);
int main()
{
long long int number;
cout<<"Enter the number of prime numbers you want to know:\n";
cin>>number; //number is the number of prime numbers to be displayed
long long int j=0;
long long int m=2; //m would be used as consecutive natural numbers on which, test of prime number is performed
while (1<2)
{
if(ifprime(m)==1)
{
j+=1; // j is the counter of the prime numbers found and displayed
cout<<m<<endl;
}
m+=1;
if(j==number)
{
break;
}
}
}
int ifprime(long long int a)
{
for(int i=2;i<a;i++)
{
if(a%i==0)
{
return 0;
}
}
return 1;
}
The range of long long int seems to be small compared to the biggest primes known :/
Even if I were to compute the last prime number in the range of the long long int , can I compute the time it would take to compute that number?
Let's say the biggest prime number was n = 13. Your program would then try the following numbers: 2, 3, 4,.. 11, 12
So you have to test your number n - 2 times (which is more or less n times) and until you reach that point your program has to go through 2, 3, 4, ... 11, 12, 13, which is also (more or less) n times. -->The complexity is O(n^2).
Simple tip to speed up your program: store every prime number you've found so far in std::vector and only try these. This way you avoid integer factorization (like dividing with 6 (2 * 3) or 8 (2 * 2 * 2)).
I'm very new to C++, and programming in general. I decided that I wanted to make a "Guess the Number" game, but I wanted see how many guesses on average it would take the computer to guess a number between 1 and 10,000,000.
The easiest way that I could think of finding the "secret" number was to
1. take the range and divide it by two(divisor) and that would be the guess.
a. if the guess is greater than the "secret" number, then the guess-1 becomes the new maximum of the range, and I go back to step 1.
b. if the guess is lower than the "secret" number, then the guess+1 becomes the new minimum of the range and I go back to step 1.
This repeats until the number is found. From my experience, it takes the computer 22 guesses to guess the "secret" number.
For fun, I wanted to see what would happen if I changed the divisor. I was actually a bit surprised by the results for 1,000,000 iterations of trying to guess the number between 1 and 10,000,000 for a range of divisors from 2 to 10.
Average with divisor 2 is 22.3195
Average with divisor 3 is 20.5549
Average with divisor 4 is 20.9087
Average with divisor 5 is 22.0998
Average with divisor 6 is 23.1571
Average with divisor 7 is 25.5232
Average with divisor 8 is 25.927
Average with divisor 9 is 27.1941
Average with divisor 10 is 28.0839
I would love to understand why when the divisors 3, 4, and 5, are used the computer is able to, on average, use less guesses to find the "secret" number.
My code is below.
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <vector>
using namespace std;
int half_search(int a, int b, int n, int m)
{
int aMax = b;
int aMin = a;
int divisor = m;
int result;
static int counter = 0;
double guess = ((static_cast<double>(b) - a) / divisor) + aMin;
if(guess - static_cast<int>(guess) >= 0.5)
guess = ceil(guess);
if(guess < n)
{
aMin = guess + 1;
counter++;
half_search(aMin, aMax, n, divisor);
}
else if(guess > n)
{
aMax = guess - 1;
counter++;
half_search(aMin, aMax, n, divisor);
}
else
{
counter++;
result = counter;
counter = 0;
return result;
}
}
int main()
{
const int MIN = 1;
const int MAX = 10000000;
int k = 0;
int j = 2; //represents lowest divisor
int l = 10; //represent highest divisor
int iterations = 100000;
double stepSum = 0;
vector<int> myVector(iterations);
srand(1);
while(j <=10)
{
while(k < iterations)
{
int n = rand() % MAX + 1;
myVector[k] = half_search(MIN, MAX, n, j);
stepSum += myVector[k];
k++;
}
cout << "Average with divisor " << j << " is " << stepSum / iterations << endl;
j++;
k = 0;
stepSum = 0;
}
return 0;
}
On some compilers (e.g Visual Studio 2013) int n = rand() % MAX + 1; will only provide a number between 1 and 32768 because RAND_MAX can be as low as 32767.
If your random number is quite small this will bias in favour of a larger divisor.
Consider using <random> in C++11 instead. Something like:
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<> dist(1, MAX);
//...
int n = dist(mt);
The division by 2 would be always faster, and increment the performance, because it is easier for the CPU and takes less clock cycles. This is known as Binary Search.
By using other divisor, you could have less "guesses" until the point that it has to ask to many times where the "secret" is greater or lower than the "guess".
I also see best result with divisor 2. This also should be the case Because by using divisor 2 you are only employing binary search algorithm as each time your input set would be halved.
I want to find total factors of any number.
In number theory, factorization is the breaking down of a composite number into smaller non-trivial divisors, which when multiplied together equal the original integer. Your job is to calculate number of unique factorization(containing at least two positive integers greater than one) of a number.
For example: 12 has 3 unique factorizations: 2*2*3, 2*6, 3*4 . Note:
3*4 and 4*3 are not considered different.
I have attempted to find that but not getting exact for all.
Here is my code :
#include<iostream>
using namespace std;
int count=0;
void factor(int n,int c,int n1)
{
for(int i=n1; i<n ; i++)
{
if(c*i==n)
{count++;
return;}
else
if(c*i>n)
return;
else
factor(n,c*i,i+1);
}
return;
}
int main()
{
int num,n;
cin>>num;
for(int i=0 ; i<num ; i++)
{
cin>>n;
count=0;
factor(n,1,1);
cout<<count<<endl;
}
return 0;
}
Input is number of test cases followed by test-cases(Numbers).
Example : Input: 3 12 36 3150
Output: 3 8 91
I think you are looking for number of factorizations of a number which are unique.
For this I think you need to find the count of number of prime factor of that number. Say for
12 = 2, 2, 3
Total count = 3;
For 2, 2, 3 we need
(2*2)*3 ~ 4*3
2*(2*3) ~ 2*6
2*2*3 ~ 2*2*3
To solve this we have idea found in Grimaldi, discrete and combinatorial mathematics.
To find number of ways of adding to a number(n) is 2^(n-1) -1. For 3 we have...
3 =
1+1+1
2+1
1+2
Total count = 2^(3-1) -1 = 4-1 = 3
We can use analogy to see that
1+1+1 is equivalent to 2*2*3
1+2 is equivalent to 2*(2*3)
2+1 is equivalent to (2*2)*3
Say number of prime factors = n
So we have number of factorizations = 2^(n-1)-1
The code:
#include <stdio.h>
int power(int x, int y)
{
int prod =1, i ;
for(i=1; i<=y;i++) prod *= x;
return prod;
}
int main()
{
int number,div;
int count = 0, ti, t;
printf("Input: ");
scanf("%d",&t);
for(ti=1; ti<=t;ti++)
{
scanf("%d", &number);
div = 2;count = 0;
while(number != 0)
{
if(number%div!=0) div = div + 1;
else
{
number = number / div;
//printf("%d ",div);
count++;
if(number==1) break;
}
}
printf("%d ", power(2,count-1)-1);
}
return 0;
}
Using mod is really useful in attempting to factor:
for(int i = 1; i <= fnum; ++i){ //where fnum is the number you wish to factor
if(!(fnum % i)) ++count;
}
return count;
Of cross this is the number of factors, not unique factors, if you want the number of unique factors, you have to do some additional work.
The solution is to realize that of all permutations, precisely one is sorted. 2 * 4 * 7 * 3 gives the same result as 2 * 3 * 4 * 7. That means that when you've found one factor, you should not check the remainder for lower factors. However, you should check if the same factor appears again: 12 = 2 * 2 * 3. The sequence 2 2 3 is also sorted.
BTW, you should give your variables clearer names, or at least add some comments describing them.
here x,y<=10^12 and y-x<=10^6
i have looped from left to right and checked each number for a prime..this method is very slow when x and y are somewhat like 10^11 and 10^12..any faster approach?
i hv stored all primes till 10^6..can i use them to find primes between huge values like 10^10-10^12?
for(i=x;i<=y;i++)
{
num=i;
if(check(num))
{
res++;
}
}
my check function
int check(long long int num)
{
long long int i;
if(num<=1)
return 0;
if(num==2)
return 1;
if(num%2==0)
return 0;
long long int sRoot = sqrt(num*1.0);
for(i=3; i<=sRoot; i+=2)
{
if(num%i==0)
return 0;
}
return 1;
}
Use a segmented sieve of Eratosthenes.
That is, use a bit set to store the numbers between x and y, represented by x as an offset and a bit set for [0,y-x). Then sieve (eliminate multiples) for all the primes less or equal to the square root of y. Those numbers that remain in the set are prime.
With y at most 1012 you have to sieve with primes up to at most 106, which will take less than a second in a proper implementation.
This resource goes through a number of prime search algorithms in increasing complexity/efficiency. Here's the description of the best, that is PG7.8 (you'll have to translate back to C++, it shouldn't be too hard)
This algorithm efficiently selects potential primes by eliminating multiples of previously identified primes from consideration and
minimizes the number of tests which must be performed to verify the
primacy of each potential prime. While the efficiency of selecting
potential primes allows the program to sift through a greater range of
numbers per second the longer the program is run, the number of tests
which need to be performed on each potential prime does continue to
rise, (but rises at a slower rate compared to other algorithms).
Together, these processes bring greater efficiency to generating prime
numbers, making the generation of even 10 digit verified primes
possible within a reasonable amount of time on a PC.
Further skip sets can be developed to eliminate the selection of potential primes which can be factored by each prime that has already
been identified. Although this process is more complex, it can be
generalized and made somewhat elegant. At the same time, we can
continue to eliminate from the set of test primes each of the primes
which the skip sets eliminate multiples of, minimizing the number of
tests which must be performed on each potential prime.
You can use the Sieve of Eratosthenes algorithm. This page has some links to implementations in various languages: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes.
Here is my implementation of Sieve of Erathostenes:
#include <string>
#include <iostream>
using namespace std;
const int k = 110000; //you can change this constant to whatever maximum int you would need to calculate
long int p[k]; //here we would store Sieve of Erathostenes from 2 to k
long int j;
void init_prime() //in here we set our array
{
for (int i = 2; i <= k; i++)
{
if (p[i] == 0)
{
j = i;
while (j <= k)
{
p[j] = i;
j = j + i;
}
}
}
/*for (int i = 2; i <= k; i++)
cout << p[i] << endl;*/ //if you uncomment this you can see the output of initialization...
}
string prime(int first, int last) //this is example of how you can use initialized array
{
string result = "";
for (int i = first; i <= last; i++)
{
if (p[i] == i)
result = result + to_str(i) + "";
}
return result;
}
int main() //I done this code some time ago for one contest, when first input was number of cases and then actual input came in so nocases means "number of cases"...
{
int nocases, first, last;
init_prime();
cin >> nocases;
for (int i = 1; i <= nocases; i++)
{
cin >> first >> last;
cout << prime(first, last);
}
return 0;
}
You can use the Sieve of Erathostenes to calculate factorial too. This is actually the fastest interpretation of the Sieve I could manage to create that day (it can calculate the Sieve of this range in less than a second)