This question already has answers here:
A better algorithm to find the next palindrome of a number string
(10 answers)
Next higher prime and palindrome number
(4 answers)
Closed 7 years ago.
Here's the actual question
https://www.codechef.com/problems/PRPALIN/
The following code works well on all inputs but on input of 900000 the execution time is 1.125sec. How do I optimize the code? How can the code be improved?
Any help is greatly appreciated. Thank You! :)
#include <iostream>
#include <cmath>
#include <cassert>
#include <ctime>
clock_t start=clock();
long long a;
inline long long next_prime();
inline bool palindrome();
int main()
{
freopen("in.txt","r",stdin);
scanf("%ld", &a);
assert(1 <= a <= 1000000);
do
a = next_prime();
while(!palindrome());
printf("%ld\n",a);
fprintf(stderr,"time=%.3lfsec\n",0.001*(clock()-start));
return 0;
}
long long next_prime()
{
long long num = a;
num++;
while(1)
{
int flag = 0;
long long i;
long long z = sqrt(num);
for(i = 2; i <= z; i++)
if((num % i) == 0)
flag = 1;
if(flag == 0)
return num;
else
num++;
}
}
bool palindrome()
{
long long reverse_num = 0;
long long temp = a;
while(temp != 0)
{
reverse_num = reverse_num * 10;
reverse_num = reverse_num + temp % 10;
temp = temp/10;
}
if(a == reverse_num)
return true;
else
return false;
}
You can optimize the detecting prime function by using the following algorithm.
Create a list of consecutive integers from 2 through n: (2, 3, 4, ..., n).
Initially, let p equal 2, the first prime number.
Starting from p, enumerate its multiples by counting to n in increments of p, and mark them in the list (these will be 2p, 3p, 4p, ... ; the p itself should not be marked).
Find the first number greater than p in the list that is not marked. If there was no such number, stop. Otherwise, let p now equal this new number (which is the next prime), and repeat from step 3.
Check this link, http://www.algolist.net/Algorithms/Number_theoretic/Sieve_of_Eratosthenes
As for the palindrome check, it's currently O(n), I can't think of any way to improve upon that.
Related
I'm trying to write a c++ program which gets an integer n (n>=1 && n<=100000) from the user and puts the sum of its digits into b. The output needed is the b-th prime number coming after n. I'm an absolute beginner in programming so I don't know what's wrong with the for loop or any other code that it doesn't show the correct output. For example the 3rd prime number after 12 (1+2=3) is 19 but the loop counts the prime numbers from 2 instead of 12, so it prints 7 as result.
#include <iostream>
using namespace std;
bool isPrime(int n)
{
if(n <= 1)
return false;
for(int i = 2; i <= (n/2); i++)
if(n % i == 0)
return false;
return true;
}
int main()
{
long int n;
int b = 0;
cin>>n;
while(n >= 1 && n <= 100000){
b += n % 10;
n /= 10;
}
for(int i = n, counter = b; counter <= 10; i++)
if(isPrime(i)){
counter++;
if(i > n)
cout<<counter<<"th prime number after n is : "<<i<<endl;
}
return 0;
}
So one of the possible solutions to my question, according to #Bob__ answer (and converting it to the code style I've used in the initial code) is as follows:
#include <iostream>
using namespace std;
bool isPrime(long int number)
{
if(number <= 1)
return false;
for(int i = 2; i <= (number / 2); i++)
if(number % i == 0)
return false;
return true;
}
int sumOfDigits(long int number)
{
int sum = 0;
while(number >= 1 && number <= 100000)
{
sum += number % 10;
number /= 10;
}
return sum;
}
long int bthPrimeAfter(int counter, long int number)
{
while(counter)
{
++number;
if(isPrime(number))
--counter;
}
return number;
}
int main()
{
long int number;
cin>>number;
int const counter = sumOfDigits(number);
cout<<bthPrimeAfter(counter, number)<<"\n";
return 0;
}
As dratenik said in their comment:
You have destroyed the value in n to produce b in the while loop. When the for loop comes around, n keeps being zero.
That's a key point to understand, sometimes we need to make a copy of a variable. One way to do that is passing it to a function by value. The function argument will be a local copy which can be changed without affecting the original one.
As an example, the main function could be written like the following:
#include <iostream>
bool is_prime(long int number);
// ^^^^^^^^ So is `n` in the OP's `main`
int sum_of_digits(long int number);
// ^^^^^^^^^^^^^^^ This is a local copy.
long int nth_prime_after(int counter, long int number);
int main()
{
long int number;
// The input validation (check if it's a number and if it's in the valid range,
// deal with errors) is left to the reader as an exercise.
std::cin >> number;
int const counter = sum_of_digits(number);
std::cout << nth_prime_after(counter, number) << '\n';
return 0;
}
The definition of sum_of_digits is straightforward.
int sum_of_digits(long int number)
{
int sum = 0;
while ( number ) // Stops when number is zero. The condition n <= 100000
{ // belongs to input validation, like n >= 0.
sum += number % 10;
number /= 10; // <- This changes only the local copy.
}
return sum;
}
About the last part (finding the nth prime after the chosen number), I'm not sure to understand what the asker is trying to do, but even if n had the correct value, for(int i = n, counter = b; counter <= 10; i++) would be just wrong. For starters, there's no reason for the condition count <= 10 or at least none that I can think of.
I'd write something like this:
long int nth_prime_after(int counter, long int number)
{
while ( counter )
{
++number;
if ( is_prime(number) )
{
--counter; // The primes aren't printed here, not even the nth.
}
}
return number; // Just return it, the printing is another function's
} // responsabilty.
A lot more could be said about the is_prime function and the overall (lack of) efficiency of this algorithm, but IMHO, it's beyond the scope of this answer.
I'm making a simple program to calculate the number of pairs in an array that are divisible by 3 array length and values are user determined.
Now my code is perfectly fine. However, I just want to check if there is a faster way to calculate it which results in less compiling time?
As the length of the array is 10^4 or less compiler takes less than 100ms. However, as it gets more to 10^5 it spikes up to 1000ms so why is this? and how to improve speed?
#include <iostream>
using namespace std;
int main()
{
int N, i, b;
b = 0;
cin >> N;
unsigned int j = 0;
std::vector<unsigned int> a(N);
for (j = 0; j < N; j++) {
cin >> a[j];
if (j == 0) {
}
else {
for (i = j - 1; i >= 0; i = i - 1) {
if ((a[j] + a[i]) % 3 == 0) {
b++;
}
}
}
}
cout << b;
return 0;
}
Your algorithm has O(N^2) complexity. There is a faster way.
(a[i] + a[j]) % 3 == ((a[i] % 3) + (a[j] % 3)) % 3
Thus, you need not know the exact numbers, you need to know their remainders of division by three only. Zero remainder of the sum can be received with two numbers with zero remainders (0 + 0) and with two numbers with remainders 1 and 2 (1 + 2).
The result will be equal to r[1]*r[2] + r[0]*(r[0]-1)/2 where r[i] is the quantity of numbers with remainder equal to i.
int r[3] = {};
for (int i : a) {
r[i % 3]++;
}
std::cout << r[1]*r[2] + (r[0]*(r[0]-1)) / 2;
The complexity of this algorithm is O(N).
I've encountered this problem before, and while I don't find my particular solution, you could improve running times by hashing.
The code would look something like this:
// A C++ program to check if arr[0..n-1] can be divided
// in pairs such that every pair is divisible by k.
#include <bits/stdc++.h>
using namespace std;
// Returns true if arr[0..n-1] can be divided into pairs
// with sum divisible by k.
bool canPairs(int arr[], int n, int k)
{
// An odd length array cannot be divided into pairs
if (n & 1)
return false;
// Create a frequency array to count occurrences
// of all remainders when divided by k.
map<int, int> freq;
// Count occurrences of all remainders
for (int i = 0; i < n; i++)
freq[arr[i] % k]++;
// Traverse input array and use freq[] to decide
// if given array can be divided in pairs
for (int i = 0; i < n; i++)
{
// Remainder of current element
int rem = arr[i] % k;
// If remainder with current element divides
// k into two halves.
if (2*rem == k)
{
// Then there must be even occurrences of
// such remainder
if (freq[rem] % 2 != 0)
return false;
}
// If remainder is 0, then there must be two
// elements with 0 remainder
else if (rem == 0)
{
if (freq[rem] & 1)
return false;
}
// Else number of occurrences of remainder
// must be equal to number of occurrences of
// k - remainder
else if (freq[rem] != freq[k - rem])
return false;
}
return true;
}
/* Driver program to test above function */
int main()
{
int arr[] = {92, 75, 65, 48, 45, 35};
int k = 10;
int n = sizeof(arr)/sizeof(arr[0]);
canPairs(arr, n, k)? cout << "True": cout << "False";
return 0;
}
That works for a k (in your case 3)
But then again, this is not my code, but the code you can find in the following link. with a proper explanation. I didn't just paste the link since it's bad practice I think.
I have the following problem, as says in the title: For each value of N, print out how many digits are in N!. For example, if n=32000, I should get 130271.
I have thought about a recursive solution. It works for smaller numbers, but for the above example it prints 31997. I am convinced that my thinking is wrong, but I can't really find a rule for bigger numbers. Somewhere, n! begins to skip steps, I think. I mean, it does not increases with a digit, but with two or three.
I have the following code:
#include <stdio.h>
#include <stdlib.h>
//For each value of N, print out how many digits are in N!.
int how_many(int n){
if( n <= 3)
return 1;
if( n == 4)
return 2;
if( n == 5 || n == 6)
return 3;
if( n >= 7)
return 1 + how_many(n-1);
}
int main()
{
int n;
printf("The number n is : ");
scanf("%d", &n);
int counter = 0;
counter = how_many(n);
printf("n! has %d digits", counter);
return 0;
}
What you're doing is really log10(N!). Once you realize that, you can use Stirling's Approximation or one of the other techniques explored here: https://math.stackexchange.com/questions/138194/approximating-log-of-factorial
The answer of #JohnZwinck solved my problem. Here is the resulting code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define M_PI 3.14159265358979323846
//For each value of N, print out how many digits are in N!.
int digits_in_factorial(int n){
return floor((n+0.5)*log(n) - n+ 0.5*log(2*M_PI))/log(10) + 1;
}
int main()
{
int n;
printf("Numarul n este : ");
scanf("%d", &n);
int counter = 0;
counter = digits_in_factorial(n);
printf("n! are %d cifre", counter);
return 0;
}
OP's recursive method estimates too low:
return 1 + how_many(n-1);
Should be more like
return log10(n) + how_many(n-1);
Using OP's original integer approach and below how_many(32000) --> n! has 123560 digits - a better estimate.
int how_many(int n) {
if (n <= 3)
return 1;
if (n == 4)
return 2;
if (n == 5 || n == 6)
return 3;
int count = 0 + how_many(n - 1);
while (n > 3) {
n /= 10;
count++;
}
return count;
}
IAC, OP has found Stirling's method.
This question already has answers here:
nth fibonacci number in sublinear time
(16 answers)
Closed 6 years ago.
I have seen a task on an online test with competitive programming challenges (cannot disclose unfortunately where) to produce last (least significant) 6 digits of Nth Fibonacci number.
I have managed to come up with the following solution:
#include <iostream>
#include <cassert>
#include <tuple>
int solution(int N)
{
if(N == 0) return 0;
if(N == 1) return 1;
if(N == 2) return 1;
int a = 0;
int b = 1;
int c = 1;
for (int i = 3; i <= N; ++i) {
std::tie(a, b, c) = std::make_tuple(b, (a + b) % 1000000, (b + c) % 1000000);
}
return c;
}
int main()
{
assert(solution(8) == 21);
assert(solution(36) == 930352);
std::cout << solution(10000000) << std::endl;
}
which unfortunately has O(N) time complexity and start to run quite slow for inputs like in the last line: N > 10000000.
Anyone knows how this can be achieved in O(logN)?
There is an algorithm taking O(log_n) time to compute nth Fibonacci number using Q-Matrix. You can take a look at http://kukuruku.co/hub/algorithms/the-nth-fibonacci-number-in-olog-n, the only change you will need is to make sure it produce only last 6 digits.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I tried implementing the segmented sieve algorithm for this [question]:http://www.spoj.pl/problems/PRIME1/ as follows :
#include <iostream>
#include <string>
#include <set>
#include<math.h>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cstdio>
#define MAX 32000 // sqrt of the upper range
using namespace std;
int base[MAX]; // 0 indicates prime
vector<int> pv; // vector of primes
int mod (int a, int b)
{
if(b < 0)
return mod(-a, -b);
int ret = a % b;
if(ret < 0)
ret+=b;
return ret;
}
void sieve(){
for(int i = 2 ; i * i < MAX ; i++ )
if(!base[i])
for(int j = i * i ; j < MAX ; j += i )
base[j] = 1;
for(int i = 2 ; i < MAX ; i++ )
if(!base[i]) pv.push_back(i);
}
int fd_p(int p ,int a ,int b){ // find the first number in the range [a,b] which is divisible by prime p
/* while(1){
if(a % p == 0 && a !=p) break;
a++;
}
return a;
*/
if(a != p){
return (a + mod(-a,p)) ;
}
else{
return (a + p);
}
}
void seg_sieve(int a , int b){
if(b < 2 ){
cout << "" ;
return;
}
if(a < 2){
a = 2;
}
int i,j;
int seg_size = b - a + 1;
int*is_prime = new int[seg_size];
memset(is_prime,0,seg_size*sizeof(int));
vector<int> :: iterator p ;
for(p = pv.begin(); p!=pv.end(); p++){
int x = fd_p(*p,a,b);
for(i = x; i <= b; i += *p )
is_prime[i - a] = 1;
}
for(i=0; i < b - a + 1; i++)
if(!is_prime[i])
printf("%u\n", i + a);
delete []is_prime ;
}
int main()
{
sieve();
int a,b,T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&a,&b);
seg_sieve(a,b);
printf("\n");
}
// cout<<endl;
// system("PAUSE");
return 0;
}
I am getting TLE nevertheless .. I don't understand what other optimization would be required . Plz help ..
Edit 1 :just tried to implement fd_p() in constant time ... [failure] .. plz if u could help me with this bug..
Edit 2:Issue Resolved.
You can get the first number in the interval [a,b] that is divisible by p in constant time. Try to do that and I think you should be good to go.
I have solved this problem many years ago. Assume, that n-m <= 100000
All you need to calculate all Primes between 1 and sqrt(1000000000) < 40000.
Than manually test each number between n and m. This will be ehough
program prime1;
Var
t:longint;
m,n:longint;
i,j,k:longint;
prime:array of longint;
bool:boolean;
begin
SetLength(prime,1);
prime[0]:=2;
for i:=3 to 40000
do begin
j:=0; bool:=true;
while (prime[j]*prime[j]<= i ) do begin
if (i mod prime[j] = 0) then begin
bool:=false;
break;
end;
inc(j);
end;
if (bool) then begin
SetLength(prime,length(prime)+1);
prime[length(prime)-1]:=i;
end;
end;
readln(t);
for k:=1 to t do begin
readln(m,n);
for i:=m to n do begin
if (i=1) then continue;
j:=0; bool:=true;
while (prime[j]*prime[j]<= i ) do begin
if (i mod prime[j] = 0) then begin
bool:=false;
break;
end;
inc(j);
end;
if (bool) then
writeln(i);
end;
writeln;
end;
end.
You've left one last step of improvement to make. Work with the odds only.
We know that 2 is prime, and we know that no even (other than 2) is ever a prime. So there's no need to check them.
The sieve of Eratosthenes for odd primes is P = {3,5, ...} \ U {{p2, p2 + 2p, ...} | p in P}. Implementing that will be enough to get you through:
Treat 2 specially, as a separate case. Work with arrays half the normal size, where the array entry at offset i represents an odd value ao + 2*i where ao = a|1 is the least odd number not below a. That means that increment value of 2p corresponds to the increment of p in the offset in the array.
The starting odd multiple of a prime p in the offset sieve array, equal to or above p*p, is m = p*p >= ao ? p*p : ((ao+p-1)/p)*p; m = m&1 ? m : m+p;, provided that p <= sqrt_b. The corresponding offset in the sieve array is (m-ao)/2.
As a side note, your naming is confusing: is_prime is actually is_composite.
What's wrong is that your fd_p function is far too slow, incrementing a till you find a good value to start your sieve will definitely time out since a can be in the range of 1 billion.
You have the right idea though.
See this blog post for an easier to understand explanation with working code as well:
http://www.swageroo.com/wordpress/spoj-problem-2-prime-generator-prime1/