I need a program in c++ that gets a number:
LOOP:
If that number is even divide it by 2 (n=n/2)
If it's not even you can do one of this operations:
n+1
n-1
LOOP ENDS
The program should do this until n=1.
But it should do this in the most efficient and fastest way and the only hint I have is that I can use DP approach.
And the output should be numbers of operations used to calculate that number.
For example:
15->16->8->4->2->1 output:5
35->36->18->9->8->4->2->1 output:7
here's the code I wrote but it's not completed yet and it's wrong since I couldn't figure out how should I add or subtract in each step:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int n;
int h=0;
int i=0;
cout<<"Enter A Number:";
cin >> n;
int r=n;
int q=n;
cout<<r;
L1: while ( r % 2 == 0)
{
for(int m=0;r>1 && m==0 ;)
{ r=r / 2;h++;
m=r%2;
cout<<" => "<<r;
}}
while(r%2==1 && r>1)
{r=r-1;cout<<" => "<<r;h++;
goto L1;}
cout<<endl;
//**********************
cout<<q;
L2: while ( q % 2 == 0)
{
for(int m=0;q>1 && m==0 ;)
{ q=q / 2;i++;
m=q%2;
cout<<" => "<<q;
}}
while(q%2==1 && q>1)
{q=q+1;cout<<" => "<<q;i++;
goto L2;}
cout<<endl<<"First:"<<h<<endl<<"Second:"<<i<<endl;
system("pause");
}
If you want to solve it using DP:
I would state this: for each possible value 1 <=i < N find the optimal number of steps.
We use a priority queue to do this where we extract at each iteration the highest number. This is much more efficient than a vector of length N because a lot of states are unreachable (e.g. i=10 in the 15 example).
Consider that the starting state is (15,0): 15 with zero moves.
From this you create two new states (8,2) and (7,2) because for each you need two steps(add/subtract + division).
Extracting (8,2): (7,2)(4,3)
Extracting (7,2): (4,3)(3,4) Here comes DP! (7,2) would create the state (4,4) but you mantain in the queue only the minimum number of steps for the same state.
Extracting (4,3): (2,4)(3,4)
extracting(3,4): (2,4)(1,6)
Extracting (2,4): (1,5)
And that is it the solution is 5 steps.
Steps for 35:
(35,0) --- >(18,2) (17,2) -----> (17,2) (9,3) ----->
(9,3)(8,4) ----> (8,4)(5,5)(4,5) ----> (5,5)(4,5) ----->
(4,5)(3,7)(2,7)----> (3,7)(2,6) -----> (2,6)(1,9) ----> (1,7)
Solution: 7 steps.
Look if that helps you.
// Example program
#include <iostream>
#include <string>
int f (int n)
{
int iterations = 0;
while (n > 1)
{
if (n % 2 != 0)
{
std::cout << n << "->";
++n;
if (n & (n - 1))
n -= 2;
++iterations;
}
std::cout << n << "->";
n >>= 1;
++iterations;
}
std::cout << n << "->";
return iterations;
}
int main()
{
std::cout << f(15) << std::endl;
std::cout << f(41) << std::endl;
std::cout << f(43) << std::endl;
}
For use of dynamic programming, you should make recursion to get sub-solutions to the problem and then solve the problem itself. You also have to use a memory structure to hold the results of such sub-solutions.
#include <deque>
#include <iostream>
using namespace std;
int solve(deque<int>& solution, int number) {
if(number >= solution.size()) // resize to fit
solution.resize(number + 1, -1);
if(number == 1) // special case for number 1
return solution[number] = 0;
if(solution[number] != -1) // if already calculated
return solution[number];
if(number % 2 == 0) // n=n/2
return solution[number] = solve(solution, number/2) + 1;
int solutionA = solve(solution, number + 1); // n++
int solutionB = solve(solution, number - 1); // n--
return solution[number] = std::min(solutionA, solutionB) + 1; // best of n++,n--
}
int main() {
deque<int> solution;
cout << solve(solution, 35);
}
I'm not sure the code will work though.
Here's my recursive solution, verified up to 2097152 against the DP example.
The basis of it is using the value of the last two bits to determine the optimal operation. If the last bit is a 0, we always divide. If the last two bits are 11 we always increment as this transforms to 100 which enables two consecutive divide operations.
If the last two bits are 01 we decrement as this gives our next operation two consecutive divide operations vs incrementing which gives us 10.
The corner case is the number 3 where 3 -> 2 is desired over promotion to 4.
I suspect you can optimise this further by just scanning the bit pattern to determine the number of operations required. i.e. each zero requires a div op, and a set of ones can be changed into zeroes with a single addition.
#include <cstdint>
int solve_algorithmically(std::uint64_t number)
{
// If 1 there is nothing to do.
if (number <= 1)
return 0;
// Nasty hack to get around the case where number=3 & 3 == 3 will cause increment
if (number == 3)
return solve_algorithmically(number - 1) + 1;
// If we have an even number (0 in LSB)
if ((number & 1) == 0)
return solve_algorithmically(number / 2) + 1;
// If we have two consecutive 1's i.e. (...11) then increment as this wil give us two zeroes.
// The exception is the root case 3 where decrement wins.
if ((number & 3) == 3)
return solve_algorithmically(number + 1) + 1;
// The only other case ends last two bits = 01
return solve_algorithmically(number - 1) + 1;
}
int main() {
for (auto i = 1; i < 2097152; i++)
{
int alg = solve_algorithmically(i);
}
}
Related
Given the binary representation of an integer as a string s, return the number of steps to reduce it to 1 under the following rules:
If the current number is even, you have to divide it by 2.
If the current number is odd, you have to add 1 to it.
It is guaranteed that you can always reach one for all test cases.
Step 1) 13 is odd, add 1 and obtain 14.
Step 2) 14 is even, divide by 2 and obtain 7.
Step 3) 7 is odd, add 1 and obtain 8.
Step 4) 8 is even, divide by 2 and obtain 4.
Step 5) 4 is even, divide by 2 and obtain 2.
Step 6) 2 is even, divide by 2 and obtain 1.
My input = 1111011110000011100000110001011011110010111001010111110001
Expected output = 85
My output = 81
For the above input, the output is supposed to be 85. But my output shows 81. For other test cases it
seems to be giving the right answer. I have been trying all possible debugs, but I am stuck.
#include <iostream>
#include <string.h>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s =
"1111011110000011100000110001011011110010111001010111110001";
long int count = 0, size;
unsigned long long int dec = 0;
size = s.size();
// cout << s[size - 1] << endl;
for (int i = 0; i < size; i++)
{
// cout << pow(2, size - i - 1) << endl;
if (s[i] == '0')
continue;
// cout<<int(s[i])-48<<endl;
dec += (int(s[i]) - 48) * pow(2, size - 1 - i);
}
// cout << dec << endl;
// dec = 278675673186014705;
while (dec != 1)
{
if (dec % 2 == 0)
dec /= 2;
else
dec += 1;
count += 1;
}
cout << count;
return 0;
}
This line:
pow(2, size - 1 - i)
Can face precision errors as pow takes and returns doubles.
Luckily, for powers base 2 that won't overflow unsigned long longs, we can simply use bit shift (which is equivalent to pow(2, x)).
Replace that line with:
1LL<<(size - 1 - i)
So that it should look like this:
dec += (int(s[i]) - 48) * 1ULL<<(size - 1 - i);
And we will get the correct output of 85.
Note: as mentioned by #RSahu, you can remove (int(s[i]) - 48), as the case where int(s[i]) == '0' is already caught in an above if statement. Simply change the line to:
dec += 1ULL<<(size - 1 - i);
The core problem has already been pointed out in answer by #Ryan Zhang.
I want to offer some suggestions to improve your code and make it easier to debug.
The main function has two parts -- first part coverts a string to number and the second part computes the number of steps to get the number to 1. I suggest creating two helper functions. That will allow you to debug each piece separately.
int main()
{
string s = "1111011110000011100000110001011011110010111001010111110001";
unsigned long long int dec = stringToNumber(s);
cout << "Number: " << dec << endl;
// dec = 278675673186014705;
int count = getStepsTo1(dec);
cout << "Steps to 1: " << count << endl;
return 0;
}
Iterate over the string from right to left using std::string::reverse_iterator. That will obviate the need for size and use of size - i - 1. You can just use i.
unsigned long long stringToNumber(string const& s)
{
size_t i = 0;
unsigned long long num = 0;
for (auto it = s.rbegin(); it != s.rend(); ++it, ++i )
{
if (*it != '0')
{
num += 1ULL << i;
}
}
return num;
}
Here's the other helper function.
int getStepsTo1(unsigned long long num)
{
long int count = 0;
while (num != 1 )
{
if (num % 2 == 0)
num /= 2;
else
num += 1;
count += 1;
}
return count;
}
Working demo: https://ideone.com/yerRfK.
According to Numberphile if (n) number of soldiers is a power of 2 regardless of starting position the answer will always be the starting position
please refer to this image... and if not please refer to this image i hope you understand my simple illustration on the problem thank you...
/*
formulas: *1 if (n) is power of 2 then the answer is 1
*W(n) = 2l + 1
version 0.4
*/
#include<iostream>
#include<string>
using namespace std;
bool isPowerofTwo(int n){
return (n & (n - 1)) == 0;
}
int bin_to_dec(long n){
int dec = 0, i = 0, rem, base = 1;
while (n != 0) {
dec += (n % 10) * base;
n /= 10;
base *= 2;
}
return dec;
}
int main(){
//var1: input of (n) var2: bin as "binary var3: str for string"
unsigned int n, i, bin;
string str;
cout<<"Input (n): ";
cin>>n;
if(isPowerofTwo(n)){
cout<<"The safe position is no. " << 1 << endl;
} else {
while(n!=0){//decimal to binary conversion
str = (n % 2 == 0 ? "0":"1") + str;
n/=2;
}
str.erase(0,1); //erasing the largest binary (the leftmost because it is not needed)
bin = stoi(str); //converting string to int
cout<<"The safe position is no. " << (bin_to_dec(bin) * 2) + 1; //converting binary to get the 2l+1
}
return 0;
}
#include<math.h>
bool isPowerofTwo(int n){
return (ceil(log2(n)) == floor(log2(n)));
}
The definition of ceil() is double ceil(double x);. Same goes for floor() and log2(). You are calling some expensive floating point functions here that are also inprecise.
bool isPowerofTwo(usigned int n) {
return (n & (n - 1)) == 0;
}
Subtracting 1 will turn the lowest 1 bit in n into a 0. The bitwise AND then eliminates the lowest 1 bit in n. If n is a power of 2 then it has only 1 bit set. That means the AND gives 0.
In main also use unsigned int for everything that can't be negative. It often produces simpler code, like for example n % 2 can be complicated if the cpus % operation gives different results for negative numbers than the standard requires (or you use MSVC and it thinks that's the case).
I'm trying to solve the 2nd problem on Project Euler where I have to print the sum of all even Fibonacci numbers under 4 million. I'm using the following code but the program is not returning any value. When I replace 4000000 by something small like 10, I get the sum. Does that mean my program is taking too long? What am I doing wrong?
#include <iostream>
using namespace std;
int fibonacci(int i) {
if (i == 2)
return 2;
else if (i == 1)
return 1;
else return fibonacci(i - 1) + fibonacci(i - 2);
}
int main() {
int currentTerm, sum = 0;
for (int i = 1; i <= 10; i++) {
currentTerm = fibonacci(i);
if (currentTerm % 2 == 0)
sum += currentTerm;
}
cout << sum;
return 0;
}
Problem 2 of project Euler asks (emphasis mine)
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
Doing
for (int i = 1; i <= 4000000; i++)
{
currentTerm = fibonacci(i);
// ...
}
You are trying to calculate up to the 4,000,000th Fibonacci number, which is a very big beast, while you should stop around the 33th instead.
The other answers already pointed out the inefficiency of the recursive approach, but let me add some numbers to the discussion, using this slightly modified version of your program
#include <iostream>
#include <iomanip>
int k = 0;
// From https://oeis.org/A000045 The fibonacci numbers are defined by the
// recurrence relation F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
// In the project Euler question the sequence starts with 1, 2, 3, 5, ...
// So in the following I'll consider F(1) = 1 and F(2) = 2 as The OP does.
long long fibonacci(long long i)
{
++k;
if (i > 2)
return fibonacci(i - 1) + fibonacci(i - 2);
else
return i;
}
int main()
{
using std::cout;
using std::setw;
const long limit = 4'000'000;
long sum = 0;
cout << " i F(i) sum calls\n"
"-----------------------------------\n";
for (int i = 1; ; ++i)
{
long long F_i = fibonacci(i);
if ( F_i > limit ) // <-- corrected end condition
break;
if (F_i % 2 == 0)
{
sum += F_i;
cout << setw(3) << i << setw(10) << F_i
<< setw(10) << sum << setw(11) << k << '\n';
}
}
cout << "\nThe sum of all even Fibonacci numbers less then "
<< limit << " is " << sum << '\n';
return 0;
}
Once executed (live here), you can notice that the recursive function has been called more than 10,000,000 times, to calculate up to the 33th Fibonacci number.
That's simply not the right way. Memoization could help, here there's a quick benchmark comparing the recursive functions with a toy implementation of the memoization technique, which is represented by the histogram that you can't see. Because it's 300,000 times shorter than the others.
Still, that's not the "correct" or "natural" way to deal with this problem. As noted in the other answers you could simply calculate each number in sequence, given the previous ones. Enthus3d also noted the pattern in the sequence: odd, odd, even, odd, odd, even, ...
We can go even further and directly calculate only the even terms:
#include <iostream>
int main()
{
const long limit = 4'000'000;
// In the linked question the sequence starts as 1, 2, 3, 5, 8, ...
long long F_0 = 2, F_3 = 8, sum = F_0 + F_3;
for (;;)
{
// F(n+2) = F(n+1) + F(n)
// F(n+3) = F(n+2) + F(n+1) = F(n+1) + F(n) + F(n+1) = 2F(n+1) + F(n)
// F(n+6) = F(n+5) + F(n+4) = F(n+4) + F(n+3) + F(n+3) + F(n+2)
// = 2F(n+3) + F(n+4) + F(n+2) = 3F(n+3) + 2F(n+2)
// = 3F(n+3) + 2F(n+1) + 2F(n) = 3F(n+3) + F(n+3) - F(n) + 2F(n)
long long F_6 = 4 * F_3 + F_0;
if ( F_6 > limit )
break;
sum += F_6;
F_0 = F_3;
F_3 = F_6;
}
std::cout << sum << '\n'; // --> 4613732
return 0;
}
Live here.
If you need multiple Fibonacci numbers, and especially if you need all of them, do not use the recursive approach, use iteration instead:
var prev=0;
var curr=1;
var sum=0;
while(curr<4000000){
if(curr%2==0)
sum+=curr;
var temp=prev;
prev=curr;
curr+=temp;
}
console.log(sum);
The snippet is JavaScript (so it can run here), but if you make var-s to int-s, it will be C-ish enough.
But the actual problem was the loop: you do not need to calculate the first
n (4000000) Fibonacci numbers (which would lead to various overflows), but the Fibonacci numbers which are smaller than 4000000.
If you want a bit of magic, you can also build on the fact that every 3rd Fibonacci number is even, on the basis of "even+odd=>odd", "odd+even=>odd", and only "odd+odd=>even":
0 1 1 2 3 5 8...
E O O E O O E
^ O+O
^ E+O
^ O+E
^ O+O
var prev=1;
var curr=2;
var sum=0;
while(curr<4000000){
sum+=curr;
console.log("elem: "+curr,"sum: "+sum);
for(var i=0;i<3;i++){
var temp=prev;
prev=curr;
curr+=temp;
}
}
And if the question would be only the title, Addition of even fibonacci numbers (let's say, n of them), pure mathematics could do the job, using Binet's formula (described in #Silerus' answer) and the fact that it is an (a^n-b^n)/c thing, where a^n and b^n are geometric sequences, every 3rd of them also being a geometric sequence, (a^3)^n, and the sum of geometric sequences has a simple, closed form (if the series is a*r^n, the sum is a*(1-r^n)/(1-r)).
Putting everything together:
// convenience for JS->C
var pow=Math.pow;
var sqrt=Math.sqrt;
var round=Math.round;
var s5=sqrt(5);
var a=(1+s5)/2;
var a3=pow(a,3);
var b=(1-s5)/2;
var b3=pow(b,3);
for(var i=0;i<12;i++){
var nthEvenFib=round((pow(a3,i)-pow(b3,i))/s5);
var sumEvenFibs=round(((1-pow(a3,i+1))/(1-a3)-(1-pow(b3,i+1))/(1-b3))/s5);
console.log("elem: "+nthEvenFib,"sum: "+sumEvenFibs);
}
Again, both snippets become rather C-ish if var-s are replaced with some C-type, int-s in the first snippet, and mostly double-s in this latter one (the loop variable i can be a simple int of course).
You can use the Binet formula in your calculations - this will allow you to abandon the slow recursive algorithm, another option may be a non-recursive algorithm for calculating fibonacci numbers. https://en.wikipedia.org/wiki/Jacques_Philippe_Marie_Binet. Here is an example of using the Binet formula, it will be much faster than the recursive algorithm, since it does not recalculate all previous numbers.
#include <iostream>
#include <math.h>
using namespace std;
int main(){
double num{},a{(1+sqrt(5))/2},b{(1-sqrt(5))/2},c{sqrt(5)};
int sum{};
for (auto i=1;i<30;++i){
num=(pow(a,i)-pow(b,i))/c;
if (static_cast<int>(num)%2==0)
sum+=static_cast<int>(num);
}
cout<<sum;
return 0;
}
variant 2
int fib_sum(int n)
{
int sum{};
if (n <= 2) return 0;
std::vector<int> dp(n + 1);
dp[1] = 1; dp[2] = 1;
for (int i = 3; i <= n; i++)
{
dp[i] = dp[i - 1] + dp[i - 2];
if(dp[i]%2==0)
sum+=dp[i];
}
return sum;
}
You can speed up brutally by using compile time precalculations for all even Fibonacci numbers and sums using constexpre functions.
A short check with Binets formula shows, that roundabout 30 even Fibonacci numbers will fit into a 64bit unsigned value.
30 numbers can really easily been procealculated without any effort for the compiler. So, we can create a compile time constexpr std::array with all needed values.
So, you will have zero runtime overhead, making you program extremely fast. I am not sure, if there can be a faster solution. Please see:
#include <iostream>
#include <array>
#include <algorithm>
#include <iterator>
// ----------------------------------------------------------------------
// All the following wioll be done during compile time
// Constexpr function to calculate the nth even Fibonacci number
constexpr unsigned long long getEvenFibonacciNumber(size_t index) {
// Initialize first two even numbers
unsigned long long f1{ 0 }, f2{ 2 };
// calculating Fibonacci value
while (--index) {
// get next even value of Fibonacci sequence
unsigned long long f3 = 4 * f2 + f1;
// Move to next even number
f1 = f2;
f2 = f3;
}
return f2;
}
// Get nth even sum of Fibonacci numbers
constexpr unsigned long long getSumForEvenFibonacci(size_t index) {
// Initialize first two even prime numbers
// and their sum
unsigned long long f1{ 0 }, f2{ 2 }, sum{ 2 };
// calculating sum of even Fibonacci value
while (--index) {
// get next even value of Fibonacci sequence
unsigned long long f3 = 4 * f2 + f1;
// Move to next even number and update sum
f1 = f2;
f2 = f3;
sum += f2;
}
return sum;
}
// Here we will store ven Fibonacci numbers and their respective sums
struct SumOfEvenFib {
unsigned long long fibNum;
unsigned long long sum;
friend bool operator < (const unsigned long long& v, const SumOfEvenFib& f) { return v < f.fibNum; }
};
// We will automatically build an array of even numbers and sums during compile time
// Generate a std::array with n elements taht consist of const char *, pointing to Textx...Texty
template <size_t... ManyIndices>
constexpr auto generateArrayHelper(std::integer_sequence<size_t, ManyIndices...>) noexcept {
return std::array<SumOfEvenFib, sizeof...(ManyIndices)>{ { {getEvenFibonacciNumber(ManyIndices + 1), getSumForEvenFibonacci(ManyIndices + 1)}...}};
};
// You may check with Ninets formula
constexpr size_t MaxIndexFor64BitValue = 30;
// Generate the reuired number of texts
constexpr auto generateArray()noexcept {
return generateArrayHelper(std::make_integer_sequence<size_t, MaxIndexFor64BitValue>());
}
// This is an constexpr array of even Fibonacci numbers and its sums
constexpr auto SOEF = generateArray();
// ----------------------------------------------------------------------
int main() {
// Show sum for 4000000
std::cout << std::prev(std::upper_bound(SOEF.begin(), SOEF.end(), 4000000))->sum << '\n';
// Show all even numbers and their corresponding sums
for (const auto& [even, sum] : SOEF) std::cout << even << " --> " << sum << '\n';
return 0;
}
Tested with MSVC 19, clang 11 and gcc10
Compiled with C++17
Welcome to Stack Overflow :)
I have only modified your code on the loop, and kept your Fibonacci implementation the same. I've verified the code's answer on Project Euler. The code can be found below, and I hope my comments help you understand it better.
The three things I've changed are:
1) You tried to look for a number all the way until the 4,000,000 iteration rather than for the number that is less than 4,000,000. That means your program probably went crazy trying to add a number that's insanely large (which we don't need) <- this is probably why your program threw in the towel
2) I improved the check for even numbers; we know that fibonacci sequences go odd odd even, odd odd even, so we only really need to add every third number to our sum instead of checking if the number itself is even <- modulus operations are very expensive on large numbers
3) I added two lines that are commented out with couts, they can help you debug and troubleshoot your output
There's also a link here about using Dynamic Programming to solve the question more efficiently, should anyone need it.
Good luck!
#include <iostream>
using namespace std;
int fibonacci(int i) {
if (i == 2)
return 2;
else if (i == 1)
return 1;
else return fibonacci(i - 1) + fibonacci(i - 2);
}
int main() {
// need to add the sum of all even fib numbers under a particular sum
int max_fib_number = 4000000;
int currentTerm, sum = 0;
currentTerm = 1;
int i = 1;
// we do not need a for loop, we need a while loop
// this is so we can detect when our current number exceeds fib
while(currentTerm < max_fib_number) {
currentTerm = fibonacci(i);
//cout << currentTerm <<"\n";
// notice we check here if currentTerm is a valid number to add
if (currentTerm < max_fib_number) {
//cout << "i:" << i<< "\n";
// we only want every third term
// this is because 1 1 2, 3 5 8, 13 21 34,
// pattern caused by (odd+odd=even, odd+even=odd)
// we also add 1 because we start with the 0th term
if ((i+1) % 3 == 0)
sum += currentTerm;
}
i++;
}
cout << sum;
return 0;
}
Here's Your modified code which produce correct output to the project euler's problem.
#include <iostream>
using namespace std;
int fibonacci(int i) {
if (i == 2)
return 2;
else if (i == 1)
return 1;
else return fibonacci(i - 1) + fibonacci(i - 2);
}
int main() {
int currentsum, sum = 0;
for (int i = 1; i <= 100; i++) {
currentsum = fibonacci(i);
//here's where you doing wrong
if(sum >= 4000000) break; //break when sum reaches 4mil
if(currentsum %2 == 0) sum+=currentsum; // add when even-valued occurs in the currentsum
}
cout << sum;
return 0;
}
Output 4613732
Here's my Code which consists of while loop until 4million occurs in the sum with some explanation.
#include <iostream>
using namespace std;
int main()
{
unsigned long long int a,b,c , totalsum;
totalsum = 0;
a = 1; // 1st index digit in fib series(according to question)
b = 2; // 2nd index digit in fib series(according to question)
totalsum+=2; // because 2 is an even-valued term in the series
while(totalsum < 4000000){ //loop until 4million
c = a+b; // add previous two nums
a = b;
b = c;
if(c&1) continue; // if its odd ignore and if its an even-valued term add to totalsum
else totalsum+=c;
}
cout << totalsum;
return 0;
}
for people who downvoted, you can actually say what is wrong in the code instead downvoting the actual answer to the https://projecteuler.net/problem=2 is the output of the above code 4613732 , competitive programming itself is about how fast can you solve problems instead of clean code.
to find factors of number, i am using function void primeFactors(int n)
# include <stdio.h>
# include <math.h>
# include <iostream>
# include <map>
using namespace std;
// A function to print all prime factors of a given number n
map<int,int> m;
void primeFactors(int n)
{
// Print the number of 2s that divide n
while (n%2 == 0)
{
printf("%d ", 2);
m[2] += 1;
n = n/2;
}
// n must be odd at this point. So we can skip one element (Note i = i +2)
for (int i = 3; i <= sqrt(n); i = i+2)
{
// While i divides n, print i and divide n
while (n%i == 0)
{
int k = i;
printf("%d ", i);
m[k] += 1;
n = n/i;
}
}
// This condition is to handle the case whien n is a prime number
// greater than 2
if (n > 2)
m[n] += 1;
printf ("%d ", n);
cout << endl;
}
/* Driver program to test above function */
int main()
{
int n = 72;
primeFactors(n);
map<int,int>::iterator it;
int to = 1;
for(it = m.begin(); it != m.end(); ++it){
cout << it->first << " appeared " << it->second << " times "<< endl;
to *= (it->second+1);
}
cout << to << " total facts" << endl;
return 0;
}
You can check it here. Test case n = 72.
http://ideone.com/kaabO0
How do I solve above problem using above algo. (Can it be optimized more ?). I have to consider large numbers as well.
What I want to do ..
Take example for N = 864, we found X = 72 as (72 * 12 (no. of factors)) = 864)
There is a prime-factorizing algorithm for big numbers, but actually it is not often used in programming contests.
I explain 3 methods and you can implementate using this algorithm.
If you implementated, I suggest to solve this problem.
Note: In this answer, I use integer Q for the number of queries.
O(Q * sqrt(N)) solution per query
Your algorithm's time complexity is O(n^0.5).
But you are implementating with int (32-bit), so you can use long long integers.
Here's my implementation: http://ideone.com/gkGkkP
O(sqrt(maxn) * log(log(maxn)) + Q * sqrt(maxn) / log(maxn)) algorithm
You can reduce the number of loops because composite numbers are not neccesary for integer i.
So, you can only use prime numbers in the loop.
Algorithm:
Calculate all prime numbers <= sqrt(n) with Eratosthenes's sieve. The time complexity is O(sqrt(maxn) * log(log(maxn))).
In a query, loop for i (i <= sqrt(n) and i is a prime number). The valid integer i is about sqrt(n) / log(n) with prime number theorem, so the time complexity is O(sqrt(n) / log(n)) per query.
More efficient algorithm
There are more efficient algorithm in the world, but it is not used often in programming contests.
If you check "Integer factorization algorithm" on the internet or wikipedia, you can find the algorithm like Pollard's-rho or General number field sieve.
Well,I will show you the code.
# include <stdio.h>
# include <iostream>
# include <map>
using namespace std;
const long MAX_NUM = 2000000;
long prime[MAX_NUM] = {0}, primeCount = 0;
bool isNotPrime[MAX_NUM] = {1, 1}; // yes. can be improve, but it is useless when sieveOfEratosthenes is end
void sieveOfEratosthenes() {
//#see https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
for (long i = 2; i < MAX_NUM; i++) { // it must be i++
if (!isNotPrime[i]) //if it is prime,put it into prime[]
prime[primeCount++] = i;
for (long j = 0; j < primeCount && i * prime[j] < MAX_NUM; j++) { /*foreach prime[]*/
// if(i * prime[j] >= MAX_NUM){ // if large than MAX_NUM break
// break;
// }
isNotPrime[i * prime[j]] = 1; // set i * prime[j] not a prime.as you see, i * prime[j]
if (!(i % prime[j])) //if this prime the min factor of i,than break.
// and it is the answer why not i+=( (i & 1) ? 2 : 1).
// hint : when we judge 2,prime[]={2},we set 2*2=4 not prime
// when we judge 3,prime[]={2,3},we set 3*2=6 3*3=9 not prime
// when we judge 4,prime[]={2,3},we set 4*2=8 not prime (why not set 4*3=12?)
// when we judge 5,prime[]={2,3,5},we set 5*2=10 5*3=15 5*5=25 not prime
// when we judge 6,prime[]={2,3,5},we set 6*2=12 not prime,than we can stop
// why not put 6*3=18 6*5=30 not prime? 18=9*2 30=15*2.
// this code can make each num be set only once,I hope it can help you to understand
// this is difficult to understand but very useful.
break;
}
}
}
void primeFactors(long n)
{
map<int,int> m;
map<int,int>::iterator it;
for (int i = 0; prime[i] <= n; i++) // we test all prime small than n , like 2 3 5 7... it musut be i++
{
while (n%prime[i] == 0)
{
cout<<prime[i]<<" ";
m[prime[i]] += 1;
n = n/prime[i];
}
}
cout<<endl;
int to = 1;
for(it = m.begin(); it != m.end(); ++it){
cout << it->first << " appeared " << it->second << " times "<< endl;
to *= (it->second+1);
}
cout << to << " total facts" << endl;
}
int main()
{
//first init for calculate all prime numbers,for example we define MAX_NUM = 2000000
// the result of prime[] should be stored, you primeFactors will use it
sieveOfEratosthenes();
//second loop for i (i*i <= n and i is a prime number). n<=MAX_NUM
int n = 72;
primeFactors(n);
n = 864;
primeFactors(n);
return 0;
}
My best shot at performance without getting overboard with special algos.
The Erathostenes' seive - the complexity of the below is O(N*log(log(N))) - because the inner j loop starts from i*i instead of i.
#include <vector>
using std::vector;
void erathostenes_sieve(size_t upToN, vector<size_t>& primes) {
primes.clear();
vector<bool> bitset(upToN+1, true); // if the bitset[i] is true, the i is prime
bitset[0]=bitset[1]=0;
// if i is 2, will jump to 3, otherwise will jump on odd numbers only
for(size_t i=2; i<=upToN; i+=( (i&1) ? 2 : 1)) {
if(bitset[i]) { // i is prime
primes.push_back(i);
// it is enough to start the next cycle from i*i, because all the
// other primality tests below it are already performed:
// e.g:
// - i*(i-1) was surely marked non-prime when we considered multiples of 2
// - i*(i-2) was tested at (i-2) if (i-2) was prime or earlier (if non-prime)
for(size_t j=i*i; j<upToN; j+=i) {
bitset[j]=false; // all multiples of the prime with value of i
// are marked non-prime, using **addition only**
}
}
}
}
Now factoring based on the primes (set in a sorted vector). Before this, let's examine the myth of sqrt being expensive but a large bunch of multiplications is not.
First of all, let us note that sqrt is not that expensive anymore: on older CPU-es (x86/32b) it used to be twice as expensive as a division (and a modulo operation is division), on newer architectures the CPU costs are equal. Since factorisation is all about % operations again and again, one may still consider sqrt now and then (e.g. if and when using it saves CPU time).
For example consider the following code for an N=65537 (which is the 6553-th prime) assuming the primes has 10000 entries
size_t limit=std::sqrt(N);
size_t largestPrimeGoodForN=std::distance(
primes.begin(),
std::upper_limit(primes.begin(), primes.end(), limit) // binary search
);
// go descendingly from limit!!!
for(int i=largestPrimeGoodForN; i>=0; i--) {
// factorisation loop
}
We have:
1 sqrt (equal 1 modulo),
1 search in 10000 entries - at max 14 steps, each involving 1 comparison, 1 right-shift division-by-2 and 1 increment/decrement - so let's say a cost equal with 14-20 multiplications (if ever)
1 difference because of std::distance.
So, maximal cost - 1 div and 20 muls? I'm generous.
On the other side:
for(int i=0; primes[i]*primes[i]<N; i++) {
// factorisation code
}
Looks much simpler, but as N=65537 is prime, we'll go through all the cycle up to i=64 (where we'll find the first prime which cause the cycle to break) - a total of 65 multiplications.
Try this with a a higher prime number and I guarantee you the cost of 1 sqrt+1binary search are better use of the CPU cycle than all the multiplications on the way in the simpler form of the cycle touted as a better performance solution
So, back to factorisation code:
#include <algorithm>
#include <math>
#include <unordered_map>
void factor(size_t N, std::unordered_map<size_t, size_t>& factorsWithMultiplicity) {
factorsWithMultiplicity.clear();
while( !(N & 1) ) { // while N is even, cheaper test than a '% 2'
factorsWithMultiplicity[2]++;
N = N >> 1; // div by 2 of an unsigned number, cheaper than the actual /2
}
// now that we know N is even, we start using the primes from the sieve
size_t limit=std::sqrt(N); // sqrt is no longer *that* expensive,
vector<size_t> primes;
// fill the primes up to the limit. Let's be generous, add 1 to it
erathostenes_sieve(limit+1, primes);
// we know that the largest prime worth checking is
// the last element of the primes.
for(
size_t largestPrimeIndexGoodForN=primes.size()-1;
largestPrimeIndexGoodForN<primes.size(); // size_t is unsigned, so after zero will underflow
// we'll handle the cycle index inside
) {
bool wasFactor=false;
size_t factorToTest=primes[largestPrimeIndexGoodForN];
while( !( N % factorToTest) ) {
wasFactor=true;// found one
factorsWithMultiplicity[factorToTest]++;
N /= factorToTest;
}
if(1==N) { // done
break;
}
if(wasFactor) { // time to resynchronize the index
limit=std::sqrt(N);
largestPrimeIndexGoodForN=std::distance(
primes.begin(),
std::upper_bound(primes.begin(), primes.end(), limit)
);
}
else { // no luck this time
largestPrimeIndexGoodForN--;
}
} // done the factoring cycle
if(N>1) { // N was prime to begin with
factorsWithMultiplicity[N]++;
}
}
I am working on a program in which I must print out the number of primes, including 1 and 239, from 1 - 239 ( I know one and or two may not be prime numbers, but we will consider them as such for this program) It must be a pretty simple program because we have only gone over some basics. So far my code is as such, which seems like decent logical flow to me, but doesnt produce output.
#include <iostream>
using namespace std;
int main()
{
int x;
int n = 1;
int y = 1;
int i = 0;
while (n<=239)
{x = n % y;
if (x = 0)
i++;
if (y < n)
y++;
n++;
while (i == 2)
cout << n;
}
return 0;
}
The way I want this to work is to take n, as long as n is 239 or less, and preform modulus division with every number from 1 leading up to n. Every time a number y goes evenly into n, a counter will be increased by 1. if the counter is equal to 2, then the number is prime and we print it to the screen. Any help would be so greatly appreciated. Thanks
std::cout << std::to_string(2) << std::endl;
for (unsigned int i = 3; i<240; i += 2) {
unsigned int j = 3;
int sq = sqrt(i);
for (; j <= sq; j += 2) if (!(i%j)) break;
if (j>sq) std::cout << std::to_string(i) << std::endl;
}
first of all, the prime definition: A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
so you can skip all the even numbers (and hence ... i+=2).
Moreover no point to try to divide for a number greater than sqrt(i), because then it will have a divisor less than sqrt(i) and the code finds that and move to the next number.
Considering only odd numbers, means that we can skip even numbers as divisors (hence ... j+=2).
In your code there are clearly beginner errors, like (x = 0) instead of x==0. but also the logic doesn't convince. I agree with #NathanOliver, you need to learn to use a debugger to find all the errors. For the rest, good luck with the studies.
lets start with common errors:
first you want to take input from user using cin
cin>>n; // write it before starting your while loop
then,
if (x = 0)
should be:
if (x == 0)
change your second while loop to:
while (i == 2){
cout << n;
i++;
}