Faster way to check if number is divisible with specific number - c++

#include <iostream>
using namespace std;
int main()
{
long long n, k;
cin >> n >> k;
int num, count = 0;
do{
n--;
cin >> num;
if (num > 99 && (num % 10) % k == 0){
//cout << num << endl;
count++;
}
else if(num < 100 && (num % k) == 0){
//cout << num << endl;
count++;
}
}while(n);
cout << count << endl;
return 0;
}
I'm writing a program to check if a specific number is divisible by specific number inputted by user.
n = amount of numbers inputted
k = the number to check if numbers are divisible
My program works quite good so far, but it exceeds on time limit. Is there any faster algorithm or code than this to check if a number is divisible with another specific number?
Link : http://www.codechef.com/problems/INTEST/

First of all, the problem here is reading numbers from the input in a fast way, not doing the division. With that in mind, here is some code for fast reading:
vector<char> buffer(n * 10); // allocate a large buffer
cin.read(&buffer[0], buffer.size()); // fill the buffer with chars from input
buffer.resize(cin.gcount()); // cut buffer size to number of chars actually read
...
This reads the whole input file (note the buffer size that is limited by each number having less than 10 digits).
Then, convert the sequence of characters into numbers, and check each number for divisibility by k (num % k != 0, as others have noted). The code for that can be found in the "complex" solution that you posted (it occupies just 1 line of code there).

Modulo operator (%) is what you want. Example:
if (k != 0)
return n % k == 0;
or for the space sticklers:
if (k != 0)
return !(n % k);
Modulo returns the remainder of the division between the two numbers, for example 5 % 2 returns 1. If the remainder is 0, the numbers are divisible (IE 4 % 2 will return 0).
http://en.wikipedia.org/wiki/Modulo_operation

Instead of this code snippet
cin >> num;
if (num > 99 && (num % 10) % k == 0){
//cout << num << endl;
count++;
}
else if(num < 100 && (num % k) == 0){
//cout << num << endl;
count++;
}
You could write simply
cin >> num;
count += num % k == 0;

The point of the 'problem' is that the standard I/O libraries for most languages are very general purpose, and therefore may not be the optimal tools for reading or writing data when the format is well defined and performance is critical.
In this case, you're using the library functions to read from IO streams, which are a highly abstracted from the underlying storage system. Typically, the closer you get to the hardware, the faster your code will run.
I'd start by trying to use the C file IO functions like fopen and fread to read a large chunk of binary data from the file into memory, then process that memory 'in situ' scanning for numbers and counting the correct matches. Loop until theres no more lines to process, and remember it's much more efficent to read large blocks of data that small ones.

Instead of using
if ( n % k != 0 )
use,
int quotient = n/k;
if( quotient * k == n )
The modulus operator is slower than the second approach. (It took me 4.5 seconds to run the code with modulus operator and 1 second with the second approach)

Related

Is there a way to factorize large numbers in c++

I've written the following C++ code to factorize really large numbers efficiently (numbers up to 24997300729).
I have a vector containing 41000 primes approx.( I know having such a large vector isn't a good idea although but couldn't figure a way around this).
This code produces the prime factorization of moderately large numbers in no time but when it comes to numbers such as, 24997300572 the program stalls.
Here's the program below with some screenshots of the output:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cmath>
using namespace std;
vector<int> primes = {paste from
https://drive.google.com/file/d/1nGvtMMQSa9YIDkMW2jgEbJk67P7p54ft/view?usp=sharing
};
void factorize(int n) {
if (n == 1)
return;
if (find(primes.begin(), primes.end(), n) != primes.end()) {
cout << n <<" "; //if n is prime dont'proceed further
return;
}
//obtaining an iterator to the location of prime equal to or just greater than sqrt(n)
auto s = sqrt(n);
vector<int>::iterator it = lower_bound(primes.begin(), primes.end(), s);
if (it == primes.end()) {
return; // if no primes found then the factors are beyond range
}
for (auto i = it;i != primes.begin();i--) {
if (n % *i == 0)
{
cout << *i << " ";
n = n / (*i);
factorize(n);
return; // the two consecutive for() loops should never run one after another
}
}
for (auto i = it;i != primes.end();i++) {
if (n % *i == 0)
{
cout << *i << " ";
n = n / (*i);
factorize(n);
return; // the two consecutive for() loops should never run one after another
}
}
}
int main() {
unsigned int n;
cout << "Enter a number between 1 and 24997300729 ";
cin >> n;
if (n > 24997300729) {
cout << "Number out of range;";
exit(-1);
}
factorize(n);
return 0;
}
This is OK
But This is NOT!!!
I tried using long long int and long double wherever I could to over come the problem of large numbers, but that didn't help much.
Any help Would Be Greatly Appreciated
It's a little unclear (at least to me) exactly why you've structured the program the way you have.
You can fully factor a number by only looking for prime factors less than or equal to that number's square root. Any prime factor larger than those pairs with one prime factors smaller than that, so you only have to search for those to find all the prime factors. Any remaining factors can be obtained by simple division, not searching.
I'd probably generate the base of prime numbers on the fly (mostly likely using a sieve). The square root of 24'997'300'729 is (about) 158'105. A quick test shows that even without any work on optimization, a sieve of Eratosthenes will find the primes up to that limit in about 12 milliseconds.
Personally, I'd rather not have a fixed limit on the largest number the user can factor, other than the limit on the size of number we're working with, so if the user enters something close to the limit for a 64-bit number, we find all the primes that fit in 32 bits, and then use those to factor the number. This will obviously be slower than if we don't find as many primes, but a user probably won't be too surprised at the idea that factoring a larger number takes longer than factoring a smaller number.
So, implementing that, we might end up with code something like this:
#include <iostream>
#include <locale>
#include <vector>
#include <string>
using Number = unsigned long long;
auto build_base(Number limit) {
std::vector<bool> sieve(limit / 2, true);
for (Number i = 3; i < limit; i += 2) {
if (sieve[i / 2]) {
for (Number temp = i * i; temp < limit; temp += i)
if (temp & 1)
sieve[temp / 2] = false;
}
}
return sieve;
}
void factor(Number input, std::vector<bool> const &candidates)
{
while (input % 2 == 0) {
std::cout << 2 << "\t";
input /= 2;
}
for (Number i = 1; i < candidates.size(); i++) {
if (candidates[i]) {
auto candidate = i * 2 + 1;
while ((input % candidate) == 0) {
std::cout << candidate << "\t";
input /= candidate;
}
}
}
if (input != 1)
std::cout << input;
}
int main(int argc, char **argv) {
std::cout.imbue(std::locale(""));
if (argc != 2) {
std::cerr << "Usage: factor <number>\n";
return EXIT_FAILURE;
}
auto number = std::stoull(argv[1]);
auto limit = std::sqrt(number) + 1;
auto candidates = build_base(limit);
factor(number, candidates);
}
At a high level, the code works like this: we start by finding the primes up to the square root of the number the user entered. Since we want all the primes up to a limit, we use a sieve of Eratosthenes to find them. This builds a vector of bools, in which vector[n] will be true if n is prime, and false if n is composite. It does this starting from 3 (2 is a special case we kind of ignore for now) and crossing off the multiples of three. Then it finds the next number that hasn't been crossed off (which will be five, in this case), and crosses off its multiples. It continues doing that until it reaches the end of the array. To save some space, it leaves all the even numbers out of the array, because (other than that special case for 2) we already know none of them is prime.
Once we have that, we use those prime numbers to find prime factors of the number we want to factor. This proceeds pretty simply: walk through the vector of primes, and test whether each prime number divides evenly into the target number. If it does, print it out, divide it out of the target number, and continue.
At least for me, this seems to work pretty dependably, and is reasonably fast. If we wanted to do a better job of factoring larger numbers, the next big step would be to switch to a segmented sieve. This can improve the speed of the first part of the job by a pretty wide margin, allowing us (for example) to factor anything that'll fit into a 64-bit number in no more than about 10 seconds.

How can I improve my prime number program with Sieve of Eratosthenes algorithm?

My program prints all prime numbers from this expression:
((1 + sin(0.1*i))*k) + 1, i = 1, 2, ..., N.
Input Format:
No more than 100 examples. Every example has 2 positive integers on the same line.
Output Format:
Print each number on a separate line.
Sample Input:
4 10
500 100
Sample Output:
5
17
But my algorithm is not efficient enough. How can I add Sieve of Eratosthenes so it can be efficient enough to not print "Terminated due to timeout".
#include <iostream>
#include <cmath>
using namespace std;
int main() {
long long k, n;
int j;
while (cin >> k >> n) {
if (n>1000 && k>1000000000000000000) continue;
int count = 0;
for (int i = 1; i <= n; i++) {
int res = ((1 + sin(0.1*i)) * k) + 1;
for (j = 2; j < res; j++) {
if (res % j == 0) break;
}
if (j == res) count++;
}
cout << count << endl;
}
system("pause");
You can improve your speed by 10x simply by doing a better job with your trial division. You're testing all integers from 2 to res instead of treating 2 as a special case and testing just odd numbers from 3 to the square root of res:
// k <= 10^3, n <= 10^9
int main() {
unsigned k;
unsigned long long n;
while (cin >> k >> n) {
unsigned count = 0;
for (unsigned long long i = 1; i <= n; i++) {
unsigned long long j, res = (1 + sin(0.1 * i)) * k + 1;
bool is_prime = true;
if (res <= 2 || res % 2 == 0) {
is_prime = (res == 2);
} else {
for (j = 3; j * j <= res; j += 2) {
if (res % j == 0) {
is_prime = false;
break;
}
}
}
if (is_prime) {
count++;
}
}
cout << count << endl;
}
}
Though k = 500 and n = 500000000 is still going to take forty seconds or so.
EDIT: I added a 3rd mean to improve efficiency
EDIT2: Added an explanation why Sieve should not be the solution and some trigonometry relations. Moreover, I added a note on the history of the question
Your problem is not to count all the prime numbers in a given range, but only those which are generated by your function.
Therefore, I don't think that the Sieve of Eratosthenes is the solution for this particular exercise, for the following reason: n is always rather small while k can be very large. If kis very large, then the Sieve algorithm would have to generate a huge number of prime numbers, for finally use it for a small number of candidates.
You can improve the efficiency of you program by three means:
Avoid calculating sin(.) every time. You can use trigonometric relations for example. Moreover, first time you calculate these values, store them in an array and reuse these values. Calculation of sin()is very time consuming
In your test to check if a number is prime, limit the search to sqrt(res). Moreover, consider make the test with odd j only, plus 2
If a candidate res is equal to the previous one, avoid redoing the test
A few trigonometry
If c = cos(0.1) and s = sin(0.1), you can use the relations :
sin (0.1(i+1)) = s*cos (0.1*i) + c*sin(0.1*i))
cos (0.1(i+1)) = c*cos (0.1*i) - s*sin(0.1*i))
If n were large, it should be necessary to recalculate the sin() by the function regularly to avoid too much rounding error calculation. But it should not be the case here as n is always rather small.
However, as I mentioned, it is better to use only the "memorization" trick in a first step and check if it is enough.
A note on the history of this question and why this answer:
Recently, this site received several questions " how to improve my program, to count number of prime numbers generated by this k*sin() function ..." To my knowledge, these questions were all closed as duplicate, under the reason that the Sieve is the solution and was explained in a previous similar (but slightly different) question. Now, the same question reappeared under a slightly different form "How can I insert the Sieve algorithm in this program ... (with k*sin() again)". And then I realised that the Sieve is not the solution. It is not a criticism to previous closes as I made the same mistake in the understanding on the question. However, I think it is time to propose a new solution, even it is does not match the new question perfectly
When you make use of a simple Wheel factorization, you can obtain a very nice speedup of your code. Wheel factorization of order 2 makes use of the fact that all primes bigger than 3 can be written as 6n+1 or 6n+5 for natural n. This means that you only have to do 2 divisions per 6 numbers. Or even further, all primes bigger than 5 can be written as 30n+m, with m in {1,7,11,13,17,19,23,29}. ( 8 divisions per 30 numbers).
Using this simple principle, you can write the following function to test your primes (wheel {2,3}):
bool isPrime(long long num) {
if (num == 1) return false; // 1 is not prime
if (num < 4) return true; // 2 and 3 are prime
if (num % 2 == 0) return false; // divisible by 2
if (num % 3 == 0) return false; // divisible by 3
int w = 5;
while (w*w <= num) {
if(num % w == 0) return false; // not prime
if(num % (w+2) == 0) return false; // not prime
w += 6;
}
return true; // must be prime
}
You can adapt the above for the wheel {2,3,5}. This function can be used in the main program as:
int main() {
long long k, n;
while (cin >> k >> n) {
if (n>1000 && k>1000000000000000000) continue;
int count = 0;
for (int i = 1; i <= n; i++) {
long long res = ((1 + sin(0.1*i)) * k) + 1;
if (isPrime(res)) { count++; }
}
cout << count << endl;
}
return 0;
}
A simple timing gives me for the original code (g++ prime.cpp)
% time echo "6000 100000000" | ./a.out
12999811
echo "6000 100000000" 0.00s user 0.00s system 48% cpu 0.002 total
./a.out 209.66s user 0.00s system 99% cpu 3:29.70 total
while the optimized version gives me
% time echo "6000 100000000" | ./a.out
12999811
echo "6000 100000000" 0.00s user 0.00s system 51% cpu 0.002 total
./a.out 10.12s user 0.00s system 99% cpu 10.124 total
Other improvements can be made but might have minor effects:
precompute your sine-table sin(0.1*i) for i from 0 to 1000. This will avoid recomputing those sines over and over. This however, has a minor impact as most time is wasted on the primetest.
Checking if res(i) == res(i+1): this has barely any impact as, depending on n and k most consecutive res are not equal.
Use a lookup table, might be handier, this does have an impact.
original answer:
My suggestion is the following:
Precompute your sinetable sin(0.1*i) for i from 0 to 1000. This will avoid recomputing those sines over and over. Also, do it smart (see point 3)
Find the largest possible value of res which is res_max=(2*k)+1
Find all primes for res_max using the Sieve of Eratosthenes. Also, realize that all primes bigger than 3 can be written as 6n+1 or 6n+5 for natural n. Or even further, all primes bigger than 5 can be written as 30n+m, with m in {1,7,11,13,17,19,23,29}. This is what is called Wheel factorization. So do not bother checking any other number. (a tiny bit more info here)
Have a lookup table that states if a number is a prime.
Do all your looping over the lookup table.

Print divisors in order using theta(n) efficiency

I'm struggling to implement this correctly. I want to create a function that determines all of the divisors of the user input userNum and outputs them to the user. When userNum = 16 i'm getting the output 1 16 2 8. I didn't expect the order to be correct, but i'm missing 4 and am struggling to figure out why. Any thoughts? I'm trying to do this in theta(sqrt(num)) efficiency.
void PrintDivisors(int num);
int main()
{
int userNum;
//Request user number
cout << "Please input a positive integer >=2:" << endl;
cin >> userNum;
PrintDivisors(userNum);
return 0;
}
void PrintDivisors(int num)
{
int divisorCounter;
for (divisorCounter = 1; divisorCounter < sqrt(num); divisorCounter++)
{
if (num % divisorCounter == 0 && num / divisorCounter != divisorCounter)
cout << divisorCounter << endl << num / divisorCounter << endl;
else if (num % divisorCounter == 0 && num / divisorCounter == divisorCounter)
cout << divisorCounter << endl;
}
}
Update: I have all the numbers printing, but still trying to determine how to print them in order while remaining within theta sqrt(n) efficiency
Change loop termination condition operation to <=, now you will observe 4.
Get rid of sqrt function call. Better use this loop
for (divisorCounter = 1; divisorCounter * divisorCounter <= num; divisorCounter++)
Make sure to check your edge conditions carefully.
What is sqrt(num)?
What is the largest divisorCounter that will pass the test in the for loop?
Would 4 pass the test?
I think if you look carefully at that line with these three questions in mind you will squash the bug.
For making it run in sqrt(n) time complexity:
For any n = a X b. either a<=sqrt(n) or b<=sqrt(n).
So if you can find all divisors in range [1,sqrt(n)] you can find other divisors greater than sqrt(n)
You can use a for loop to traverse numbers in range 1 to sqrt(n) and find all the divisors less than sqrt(n), which at the same time you can also use to find other numbers greater than(or equal to) sqrt(n).
Suppose a number i < sqrt(n) is divisor or n. In that case the number k = n/i will also be divisor of n. But bigger than sqrt(n).
For printing numbers in sorted order:
During finding divisors in range [1,sqrt(n)] print only divisor in range [1,sqrt(n)] You can use an array/vector to store numbers in range [sqrt(n),n] and print them after the for loop ends. Here is a sample code
vector<int> otherNums;
for(i=1;i*i<n;i++) {
if(num%i==0){
cout<<i<<endl;
otherNums.push_back(n/i);
}
}
if(i*i == n) otherNums.push_back(i);
for(i=(int)v.size() - 1 ;i>=0;i--)
cout<<otherNums[i]<<endl;
This is the solution I ended up using, which saves space complexity too. I was struggling to think of effective ways to loop over the solution in ascending order, but this one runs very fast and is nicer than appending to a vector or array or some weird string concatenation.
void printDivisors(int num)
{
for (int k = 1; k*k < num; k++)
{
if (num % k == 0)
cout << k << " ";
}
for (int d = sqrt(num); d >= 1; d--)
{
if (num % d == 0)
cout << num / d << " ";
}
cout << endl;
}

basic nestled loop calculate prime numbers between 1 - 239, inclusive

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++;
}

Project Euler challenge 3: Finding the largest prime factor of a large number [duplicate]

This question already has answers here:
Finding largest prime number out of 600851475143?
(3 answers)
Closed 9 years ago.
Can't find the prime factor of 600851475143 for projecteuler. My code successfully computes the largest prime factor of the test number 13195 and every test number I throw at it, but somehow it degrades with the large prime number. Do you know why?
#include <iostream>
#include <queue>
using namespace std;
int split(int split);
int largestprimefactor(priority_queue<int> myints);
int main()
{
int response = 2;
do{
priority_queue<int> myints;
int number;
cout << "Please enter a number: ";
cin >> number;
myints.push(number);
int lcf = largestprimefactor(myints);
cout << endl << "Largest prime factor is: " << lcf;
cout << endl << "Again?(1 for yes 2 for no): ";
cin >> response;
}while(response == 1);
}
uint64_t split(uint64_t split)
{
if(split%2 != 0)
{
if((split/2))%2 == 0)
for(uint64_t i = (split/2)-1; i>1; i=i-2)
if(split%i == 0)
return i;
else
for(uint64_t i = (split/2); i>1; i=i-2)
if(split%i == 0)
return i;
return 1;
}
else
return 2;
}
int largestprimefactor(priority_queue<int> myints)
{
// largestfactor holds the next number to be tested for primeness in the queue
do{
int largestfactor = myints.top();
myints.pop();
//splat will hold the first factor split finds of the top item in the queue
int splat = split(largestfactor);
//if it holds a 1 then that means that there are no factors
if(splat != 1 && largestfactor)
{
myints.push(splat);
myints.push(largestfactor / splat);
}
else
return largestfactor;
}while(myints.top() > 1);
}
Have you considered that 600851475143 is too large to store in a 32 bit int?
Look into what your compiler provides for 64 bit integer types.
I might not be able to help you optimize your code (I'm not sure what you do in split), but here's an idea.
By the fundamental theorem of arithmetic, each number has a unique factorization into a product of primes. This means we can take a number and successively divide it by its prime factors until we reach 1. The last prime factor is the answer.
Now, you need only check prime factors up to sqrt(N). Note that this does not mean that the largest prime factor is less than sqrt(N), but that if there is a prime factor greater than sqrt(N), there is only one such prime factor.
This leads to the following O(sqrt(N)) algorithm:
long long largest_factor(long long number) {
long long result = 0;
for (long long i = 2; i * i <= number; ++i) {
if (number % i == 0) {
result = i;
while (number % i == 0)
number /= i;
}
}
if (number != 1)
return number;
return result;
}
Running this on 600851475143 gives me the right answer.
600851475143 >> 32 give 129, 600851475143 >> 64 give 3.10^-8. This number is too big to be represented as an int, but you can represent it with a 64 bit number as long long or a class designed to represent bigger integers.