Significant C++ code execution slowdown - c++

So I have to solve one USACO problem involving computing all the primes <= 100M and printing these of them which are palindromes while the restrictions are 16MB memory and 1 sec executions time. So I had to make a lot of optimisations.
Please take a look at the following block of code:
for(int i = 0; i < all.size(); ++i)
{
if(all[i] < a) continue;
else if(all[i] > b) break;
if(isPrime(all[i]))
{
char buffer[50];
//toString(all[i], buffer);
int c = all[i];
log10(2);
buffer[3] = 2;
//buffer[(int)log10(all[i])+1] = '\n';
//buffer[(int)log10(all[i])+2] = '\0';
//fputs(buffer, pFile);
}
}
Now, it executes in the satisfying 0.5 sec range, but when I change log10(2) to log10(all[i]) it skyrockets nearly to 2 seconds! For no apparent reason. I'm assigning all[i] to the variable c and it doesn't slow down the execution at all, but when I pass all[i] as parameter, it makes the code 4 times slower! Any ideas why this is happening and how I can fix it?
Whole code:
/*
ID: xxxxxxxx
PROG: pprime
LANG: C++11
*/
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <string>
#include <cstring>
#include <algorithm>
#include <list>
#include <ctime>
#include <cstdio>
using namespace std;
typedef struct number Number;
ifstream fin("pprime.in");
ofstream fout("pprime.out");
int MAXN = 100000000;
unsigned short bits[2000000] = {};
vector<int> primes;
vector<int> all;
int a, b;
short getBit(int atPos)
{
int whichNumber = (atPos-1) / 16;
int atWhichPosInTheNumber = (atPos-1) % 16;
return ((bits[whichNumber] & (1 << atWhichPosInTheNumber)) >> atWhichPosInTheNumber);
}
void setBit(int atPos)
{
int whichNumber = (atPos-1) / 16;
int atWhichPosInTheNumber = (atPos-1) % 16;
int old = bits[whichNumber];
bits[whichNumber] = bits[whichNumber] | (1 << atWhichPosInTheNumber);
}
void calcSieve()
{
for(int i = 2; i < MAXN; ++i)
{
if(getBit(i) == 0)
{
for(int j = 2*i; j <= (MAXN); j += i)
{
setBit(j);
}
primes.push_back(i);
}
}
}
int toInt(list<short> integer)
{
int number = 0;
while(!integer.empty())
{
int current = integer.front();
integer.pop_front();
number = number * 10 + current;
}
return number;
}
void toString(int number, char buffer[])
{
int i = 0;
while(number != 0)
{
buffer[i] = number % 10 + '0';
number /= 10;
}
}
void DFS(list<short> integer, int N, int atLeast)
{
if(integer.size() > N)
{
return;
}
if(!(integer.size() > 0 && (integer.front() == 0 || integer.back() % 2 == 0)) && atLeast <= integer.size())
{
int toI = toInt(integer);
if(toI <= b) all.push_back(toInt(integer));
}
for(short i = 0; i <= 9; ++i)
{
integer.push_back(i);
integer.push_front(i);
DFS(integer, N, atLeast);
integer.pop_back();
integer.pop_front();
}
}
bool isPrime(int number)
{
for(int i = 0; i < primes.size() && number > primes[i]; ++i)
{
if(number % primes[i] == 0) return false;
}
return true;
}
int main()
{
int t = clock();
ios::sync_with_stdio(false);
fin >> a >> b;
MAXN = min(MAXN, b);
int N = (int)log10(b) + 1;
int atLeast = (int)log10(a) + 1;
for(short i = 0; i <= 9; ++i)
{
list<short> current;
current.push_back(i);
DFS(current, N, atLeast);
}
list<short> empty;
DFS(empty, N, atLeast);
sort(all.begin(), all.end());
//calcSieve
calcSieve();
//
string output = "";
int ends = clock() - t;
cout<<"Exexution time: "<<((float)ends)/CLOCKS_PER_SEC<<" seconds";
cout<<"\nsize: "<<all.size()<<endl;
FILE* pFile;
pFile = fopen("pprime.out", "w");
for(int i = 0; i < all.size(); ++i)
{
if(all[i] < a) continue;
else if(all[i] > b) break;
if(isPrime(all[i]))
{
char buffer[50];
//toString(all[i], buffer);
int c = all[i];
log10(c);
buffer[3] = 2;
//buffer[(int)log10(all[i])+1] = '\n';
//buffer[(int)log10(all[i])+2] = '\0';
//fputs(buffer, pFile);
}
}
ends = clock() - t;
cout<<"\nExexution time: "<<((float)ends)/CLOCKS_PER_SEC<<" seconds";
ends = clock() - t;
cout<<"\nExexution time: "<<((float)ends)/CLOCKS_PER_SEC<<" seconds";
fclose(pFile);
//fout<<output;
return 0;
}

I think you've done this backwards. It seems odd to generate all the possible palindromes (if that's what DFS actually does... that function confuses me) and then check which of them are prime. Especially since you have to generate the primes anyway.
The other thing is that you are doing a linear search in isPrime, which is not taking advantage of the fact that the array is sorted. Use a binary search instead.
And also, using list instead of vector for your DFS function will hurt your runtime. Try using a deque.
Now, all that said, I think that you should do this the other way around. There are a huge number of palindromes that won't be prime. What's the point in generating them? A simple stack is all you need to check if a number is a palindrome. Like this:
bool IsPalindrome( unsigned int val )
{
int digits[10];
int multiplier = 1;
int *d = digits;
// Add half of number's digits to a stack
while( multiplier < val ) {
*d++ = val % 10;
val /= 10;
multiplier *= 10;
}
// Adjust for odd-length palindrome
if( val * 10 < multiplier ) --d;
// Check remaining digits
while( val != 0 ) {
if(*(--d) != val % 10) return false;
val /= 10;
}
return true;
}
This avoids the need to call log10 at all, as well as eliminates all that palindrome generation. The sieve is pretty fast, and after that you'll only have a few thousand primes to test, most of which will not be palindromes.
Now your whole program becomes something like this:
calcSieve();
for( vector<int>::iterator it = primes.begin(); it != primes.end(); it++ ) {
if( IsPalindrome(*it) ) cout << *it << "\n";
}
One other thing to point out. Two things actually:
int MAXN = 100000000;
unsigned short bits[2000000] = {};
bits is too short to represent 100 million flags.
bits is uninitialised.
To address both these issues, try:
unsigned short bits[1 + MAXN / 16] = { 0 };

Related

Buffer overrun warning

This script spreads all the digits of a number in an array, so that by doing this: spread(number)[position] you can access the digit with relative position. Now the compilers gives me a Buffer overrun warning (C6386), which I assume is caused by exceeding an array bounds (correct me if I'm wrong), but I scripted the function such that such thing doesn't happen, and the program is still malfunctioning
#include <iostream>
#include <math.h>
using namespace std;
unsigned int size(long long int num)
{
unsigned int size = 1;
while (num >= pow(10, size)) size++;
return size;
}
int* spread(int num)
{
unsigned int digit;
int* nums = new int[size(num)];
for (unsigned int P = 0; P <= size(num) - 1; P++)
{
digit = num - num / 10 * 10;
num /= 10;
nums[P] = digit; //Right in this line the program doesn't seem to behave correctly
}
return nums;
}
int main()
{
cout << split(377)[0] << endl;
cout << split(377)[1] << endl;
cout << split(377)[2] << endl;
system("PAUSE");
return 0x0;
}
/*
Output of the program:
7
7
-842150451 <-- there should be a 3 here
Press any key to continue . . .
*/
The body of your for loop interferes with your end condition:
P=0, num=377, size(num) = 3, P <= 2 = true
P=1, num=37, size(num) = 2, P <= 1 = true
P=2, num=3, size(num) = 1, P <= 0 = false
The fix is to calculate size(num) up front and use that in your loop condition:
int numdigits = size(num);
for (int P=0; P < numdigits; P++) { ... }
{
unsigned int digit;
int* nums = new int[size(num)];
int P = 0;
while(num!=0)
{
digit = num - num / 10 * 10;
num /= 10;
nums[P++] = digit; //Right in this line the program doesn't seem to behave correctly
}
return nums;
}
You will store the digit until the number is 0.
Use this condition and your Code works.
But you have memory leaks...
You have to free dynamic memory!
Update: There is a short code, which works ;-)
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<size_t> spread(int const num)
{
string number = to_string(num);
vector<size_t> digits;
for(size_t i = 0; i < number.size(); ++i)
{
digits.push_back(number[i] - '0');
}
return digits;
}
int main()
{
auto vec = spread(12345000);
for (auto elem : vec)
{
cout << elem << endl;
}
system("PAUSE");
return 0x0;
}

C++ gdb error reading variable: Cannot access memory at address

I am trying to solve a problem that it want the program to output the result of n^84601. (n=0,1,...,10)
Therefore, I try to solve it by using big integer, and it works well in small number, but segfault in bigger ones.
#include <stdlib.h>
#include <iostream>
using namespace std;
const int MX = 100000;
struct BigInt {
int ar[MX];
int len;
BigInt(int n) {
int i = 0;
while (n != 0) {
ar[i] = n % 10;
n /= 10;
i++;
}
len = i;
}
BigInt times(BigInt x) {
BigInt tmp(0);
for (int i = 0; i < len; i++) {
for (int j = 0; j < x.len; j++) {
int r = ar[i] * x.ar[j] + tmp.ar[i + j];
tmp.ar[i + j] = r % 10;
tmp.ar[i + j + 1] += r / 10;
}
}
for (int i = min(len + x.len, MX - 1);; i--) {
if (tmp.ar[i] != 0) {
tmp.len = i + 1;
break;
}
}
return tmp;
}
void print() {
for (int i = len - 1; i >= 0; i--) {
cout << ar[i];
}
cout << endl;
}
};
BigInt poww(BigInt a, int n) {
if (n == 1) {
return a;
}
BigInt x = poww(a, n / 2);
BigInt y = x.times(x);
if (n % 2 == 1) {
y = y.times(a);
}
return y;
}
int main(void) {
ios::sync_with_stdio(false);
int n;
while (cin >> n) {
if (n == 0)
cout << 0 << endl;
else if (n == 1)
cout << 1 << endl;
else
poww(BigInt(n), 86401).print();
}
return 0;
}
When I change the MX in to 10000 and 86401 into 864, it can correctly caculate 2^864. But it will segfault with 2^86401.
You have a stack overflow.
Your BigInt object is quite large: it contains 100001 ints, which is usually 400,004 bytes.
You allocate several of these on the stack (some are unnecessary: you should really pass arguments by const reference).
You have recursion.
A typical stack size limit is 8MB.
Combine above statements together, and you can see that you can have at most 20 BigInts on the stack at one time. Your recursion depth is at least 17, so creating more than one BigInt on the stack for each recursive call is guaranteed to fail.
There are a few solutions:
use more efficient encoding -- currently you are using int to hold one digit, unsigned char would be more appropriate
allocate space for digits on heap instead of on the stack. If you do that, be aware of the rule of five.

empty output on brute force task

I am working on a brute force task, but when I run my program, it gives an empty output file. Can anybody please help me fix this? The problem statement is below along with my code after that.
PROBLEM STATEMENT:
Write a program that reads two numbers (expressed in base 10):
N (1 <= N <= 15)
S (0 < S < 10000)
and then finds and prints (in base 10) the first N numbers strictly greater than S that are palindromic when written in two or more number bases (2 <= base <= 10).
Solutions to this problem do not require manipulating integers larger than the standard 32 bits.
CODE
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <fstream>
using namespace std;
string convert(int num, int base)
{
int quo = 100000;
int rem = 0;
string to_reverse;
while (quo > 0)
{
quo = num / base;
rem = num % base;
to_reverse += to_string(rem);
num /= base;
}
reverse(to_reverse.begin(), to_reverse.end());
return to_reverse;
}
bool is_pal(string conv_num)
{
string reversed_conv_num = conv_num;
reverse(reversed_conv_num.begin(), reversed_conv_num.end());
if (reversed_conv_num == conv_num)
{
return true;
}
return false;
}
int main()
{
ofstream fout("dualpal.out");
ifstream fin("dualpal.in");
int n, start;
fin >> n >> start;
vector<int> finals;
int times = 0;
for (int i = start + 1; i <= 10000; i++)
{
if (times == n)
{
for (auto x : finals)
{
fout << x << "\n";
}
break;
}
else
{
for (int j = 2; j <= 10; j++)
{
if(is_pal(convert(i, j)) == true)
{
times++;
finals.push_back(i);
}
}
}
}
return 0;
}
Try this code. I made some changes.
#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <fstream>
using namespace std;
string convert(int num, int base)
{
int quo = 100000;
int rem = 0;
string to_reverse;
ostringstream str1; /*this and the next commented lines are added because "to_string" didnt work in my compiler*/
while (quo > 0)
{
quo = num / base;
rem = num % base;
str1 << rem; //this
to_reverse += str1.str(); //and this
num /= base;
}
reverse(to_reverse.begin(), to_reverse.end());
return to_reverse;
}
bool is_pal(string conv_num)
{
string reversed_conv_num = conv_num;
reverse(reversed_conv_num.begin(), reversed_conv_num.end());
if (reversed_conv_num == conv_num)
{
return true;
}
return false;
}
int main()
{
ofstream fout;
fout.open("dualpal.out", ios::out); //open the file in binary mode
//ifstream fin("dualpal.in");
int n, start;
cin >> n >> start;
vector<int> finals;
int times = 0;
for (int i = start + 1; i <= 10000; i++)
{
if (times == n)
{
//just a simple iterator for vector
for (vector<int>::iterator it = finals.begin(); it != finals.end(); ++it)
{
fout << *it << "\n";
}
break;
}
else
{
for (int j = 2; j <= 10; j++)
{
if(is_pal(convert(i, j)) == true)
{
times++;
finals.push_back(i);
}
}
}
}
fout.close(); //close the file
return 0;
}
USE OF STRING STREAMS
int number = 1000;
ostringstream s;
s << number;
string str = s.str();
This method can be used to convert number to strings.
This code requires <sstream> header file.

Given an integer N, print numbers from 1 to N in lexicographic order

I'm trying to print the numbers from 1 to N in lexicographic order, but I get a failed output. for the following input 100, I get the 100, but its shifted and it doesn't match with the expected output, there is a bug in my code but I can not retrace it.
class Solution {
public:
vector<int> lexicalOrder(int n) {
vector<int> result;
for(int i = 1; i <= 9; i ++){
int j = 1;
while( j <= n){
for(int m = 0; m < j ; ++ m){
if(m + j * i <= n){
result.push_back(m+j*i);
}
}
j *= 10;
}
}
return result;
}
};
Input:
100
Output:
[1,10,11,12,13,14,15,16,17,18,19,100,2,20,21,22,23,24,25,26,27,28,29,3,30,31,32,33,34,35,36,37,38,39,4,40,41,42,43,44,45,46,47,48,49,5,50,51,52,53,54,55,56,57,58,59,6,60,61,62,63,64,65,66,67,68,69,7,70,71,72,73,74,75,76,77,78,79,8,80,81,82,83,84,85,86,87,88,89,9,90,91,92,93,94,95,96,97,98,99]
Expected:
[1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,22,23,24,25,26,27,28,29,3,30,31,32,33,34,35,36,37,38,39,4,40,41,42,43,44,45,46,47
Think about when i=1,j=10 what will happen in
for(int m = 0; m < j ; ++ m){
if(m + j * i <= n){
result.push_back(m+j*i);
}
}
Yes,result will push_back 10(0+10*1),11(1+10*1),12(2+10*1)..
Here is a solution:
#include <iostream>
#include <vector>
#include <string>
std::vector<int> fun(int n)
{
std::vector<std::string> result;
for (int i = 1; i <= n; ++i) {
result.push_back(std::to_string(i));
}
std::sort(result.begin(),result.end());
std::vector<int> ret;
for (auto i : result) {
ret.push_back(std::stoi(i));
}
return ret;
}
int main(int argc, char *argv[])
{
std::vector<int> result = fun(100);
for (auto i : result) {
std::cout << i << ",";
}
std::cout << std::endl;
return 0;
}
You are looping through all 2 digit numbers starting with 1 before outputting the first 3 digit number, so your approach won't work.
One way to do this is to output the digits in base 11, padded out with leading spaces to the maximum number of digits, in this case 3. Output 0 as a space, 1 as 0, 2 as 1 etc. Reject any numbers that have any non-trailing spaces in this representation, or are greater than n when interpreted as a base 10 number. It should be possible to jump past multiple rejects at once, but that's an unnecessary optimization. Keep a count of the numbers you have output and stop when it reaches n. This will give you a lexicographical ordering in base 10.
Example implementation that uses O(1) space, where you don't have to generate and sort all the numbers up front before you can output the first one:
void oneToNLexicographical(int n)
{
if(n < 1) return;
// count max digits
int digits = 1, m = n, max_digit11 = 1, max_digit10 = 1;
while(m >= 10)
{
m /= 10; digits++; max_digit11 *= 11; max_digit10 *= 10;
}
int count = 0;
bool found_n = false;
// count up starting from max_digit * 2 (first valid value with no leading spaces)
for(int i = max_digit11 * 2; ; i++)
{
int val = 0, trailing_spaces = 0;
int place_val11 = max_digit11, place_val10 = max_digit10;
// bool valid_spaces = true;
for(int d = 0; d < digits; d++)
{
int base11digit = (i / place_val11) % 11;
if(base11digit == 0)
{
trailing_spaces++;
val /= 10;
}
else
{
// if we got a non-space after a space, it's invalid
// if(trailing_spaces > 0)
// {
// valid_spaces = false;
// break; // trailing spaces only
// }
val += (base11digit - 1) * place_val10;
}
place_val11 /= 11;
place_val10 /= 10;
}
// if(valid_spaces && (val <= n))
{
cout << val << ", ";
count++;
}
if(val == n)
{
found_n = true;
i += 10 - (i % 11); // skip to next number with one trailing space
}
// skip past invalid numbers:
// if there are multiple trailing spaces then the next run of numbers will have spaces in the middle - invalid
if(trailing_spaces > 1)
i += (int)pow(11, trailing_spaces - 1) - 1;
// if we have already output the max number, then all remaining numbers
// with the max number of digits will be greater than n
else if(found_n && (trailing_spaces == 1))
i += 10;
if(count == n)
break;
}
}
This skips past all invalid numbers, so it's not necessary to test valid_spaces before outputting each.
The inner loop can be removed by doing the base11 -> base 10 conversion using differences, making the algorithm O(N) - the inner while loop tends towards a constant:
int val = max_digit10;
for(int i = max_digit11 * 2; ; i++)
{
int trailing_spaces = 0, pow11 = 1, pow10 = 1;
int j = i;
while((j % 11) == 0)
{
trailing_spaces++;
pow11 *= 11;
pow10 *= 10;
j /= 11;
}
int output_val = val / pow10;
if(output_val <= n)
{
cout << output_val << ", ";
count++;
}
if(output_val == n)
found_n = true;
if(trailing_spaces > 1)
{
i += (pow11 / 11) - 1;
}
else if(found_n && (trailing_spaces == 1))
{
i += 10;
val += 10;
}
else if(trailing_spaces == 0)
val++;
if(count == n)
break;
}
Demonstration
The alternative, simpler approach is just to generate N strings from the numbers and sort them.
Maybe more general solution?
#include <vector>
#include <algorithm>
using namespace std;
// returns true is i1 < i2 according to lexical order
bool lexicalLess(int i1, int i2)
{
int base1 = 1;
int base2 = 1;
for (int c = i1/10; c > 0; c/=10) base1 *= 10;
for (int c = i2/10; c > 0; c/=10) base2 *= 10;
while (base1 > 0 && base2 > 0) {
int d1 = i1 / base1;
int d2 = i2 / base2;
if (d1 != d2) return (d1 < d2);
i1 %= base1;
i2 %= base2;
base1 /= 10;
base2 /= 10;
}
return (base1 < base2);
}
vector<int> lexicalOrder(int n) {
vector<int> result;
for (int i = 1; i <= n; ++i) result.push_back(i);
sort(result.begin(), result.end(), lexicalLess);
return result;
}
The other idea for lexicalLess(...) is to convert integers to string before comparision:
#include <vector>
#include <algorithm>
#include <string>
#include <boost/lexical_cast.hpp>
using namespace std;
// returns true is i1 < i2 according to lexical order
bool lexicalLess(int i1, int i2)
{
string s1 = boost::lexical_cast<string>(i1);
string s2 = boost::lexical_cast<string>(i2);
return (s1 , s2);
}
You need Boost to run the second version.
An easy one to implement is to convert numbers to string, them sort the array of strings with std::sort in algorithm header, that sorts strings in lexicographical order, then again turn numbers to integer
Make a vector of integers you want to sort lexicographically, name it numbers.
Make an other vector and populate it strings of numbers in the first vector. name it strs.
Sort strs array.4. Convert strings of strs vector to integers and put it in vectors
List item
#include <cstdlib>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
string int_to_string(int x){
string ret;
while(x > 0){
ret.push_back('0' + x % 10);
x /= 10;
}
reverse(ret.begin(), ret.end());
return ret;
}
int main(){
vector<int> ints;
ints.push_back(1);
ints.push_back(2);
ints.push_back(100);
vector<string> strs;
for(int i = 0; i < ints.size(); i++){
strs.push_back(int_to_string((ints[i])));
}
sort(strs.begin(), strs.end());
vector<int> sorted_ints;
for(int i = 0; i < strs.size(); i++){
sorted_ints.push_back(atoi(strs[i].c_str()));
}
for(int i = 0; i < sorted_ints.size(); i++){
cout<<sorted_ints[i]<<endl;
}
}
As the numbers are unique from 1 to n, you can use a set of size n and insert all of them into it and then print them out.
set will automatically keep them sorted in lexicographical order if you store the numbers as a string.
Here is the code, short and simple:
void lexicographicalOrder(int n){
set<string> ans;
for(int i = 1; i <= n; i++)
ans.insert(to_string(i));
for(auto ele : ans)
cout <<ele <<"\n";
}

Iterative equivalent a recursive algorithm

I'm trying to modify this program to their equivalent iterative but it becomes very difficult to me because as yet i'm still a newbie, it comes to an algorithm that decomposes a number into its prime factors, here the code:
#include <iostream>
#include <map>
#include <cmath>
std::map< int, std::pair<int, int> > decompositions;
void descompon_number(int num, int root, int i = 2 )
{
auto iterator = decompositions.find(num);
if (iterator == decompositions.end())
{
if (num > 1 && i <= root)
{
if (num % i == 0)
{
int n = num / i;
decompositions[num] = std::make_pair(i, n);
descompon_number(n, (int) std::sqrt(n));
}
else
descompon_number(num, root, i + 1);
}
else
decompositions[num] = std::make_pair(num, 1);
}
}
void show(int num, int factor, int exponent, int see)
{
auto pair = decompositions[num];
if (num <= 1 || factor != pair.first)
{
if (see)
std::cout << factor;
if (exponent > 1 && see)
std::cout << "^" << exponent;
if (pair.first > 1 && see)
std::cout << " * ";
exponent = 0;
}
if (num > 1)
show(pair.second, pair.first, exponent + 1, see);
}
void descompon(int a, int b, int see)
{
if (a <= b)
{
descompon_number(a, (int) std::sqrt(a));
if (see)
std::cout << a << " = ";
show(a, decompositions[a].first, 0, see);
if (see)
std::cout << std::endl;
descompon(a + 1, b, see);
}
}
int main()
{
descompon(2, 100, 1);
return 0;
}
Someone can help me out with this
Finding prime factors iteratively is not very complicated.
Here's the pseudocode how to do this.
Let P be a list of the first n prime numbers, such that Pn <= sqrt(m).
array findPrimeFactors(m)
answer = new array
for p in P
while m can be divided by p
m = m / p
answer.append(p)
if m == 1
break
return answer
Note: empty array is returned if m is prime.
You can use an erastotenes' sieve to compute prime numbers, and later you can use the algorithm posted by popovitsj.
The following code can be optimized, but its main purpose is to show you how to proceed.
Complete example:
#include <iostream>
#include <vector>
using namespace std;
// Returns a vector containing the first <number> prime numbers
vector<int> erastotenes_sieve(int number)
{
vector<int> result;
int *sieve = new int[number];
for (int i = 0; i < number; i++) sieve[i] = 0;
// Traverse the sieve marking multiples.
for (int i = 2; i < number / 2; i++)
for (int j = i + i; j < number; j += i)
sieve[j] = 1;
// Collect unaffected indexes, those are prime numbers.
for (int i = 2; i < number; i++)
if (!sieve[i])
result.push_back(i);
delete [] sieve;
return result;
}
vector<int> descompon_number(int number)
{
vector<int> result;
if (number == 1 || number == 0)
{
result.push_back(number);
return result;
}
for (int &prime : erastotenes_sieve(number))
{
while (number % prime == 0 && number != 1)
{
number /= prime;
result.push_back(prime);
}
}
return result;
}
int main()
{
for (auto &i : descompon_number(20))
{
cout << i << endl;
}
return 0;
}