SPOJ PRIME1 : TLE [closed] - c++

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/

Related

Find the number of pairs of positive integers satisfying the inequality

I'm trying to solve a programming problem where I have to display the number of positive integer solutions of the inequality x² + y² < n, where n is given by the user. I've already written a code that seems to work but not as fast as I'd like it to. Is there any way to speed it up?
My current code:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
long long n, i, r, k, p, a;
cin >> k;
while (k--)
{
r = 0;
cin >> n;
p = sqrt(n);
for (i = 1; i <= p; i++)
{
a = sqrt(n - (i * i));
r += a;
if ((((i * i) + (a * a)) == n) && (a > 0))
{
r--;
}
}
cout << r << "\n";
}
return 0;
}
Edit:
This is a solution for this task.
The task in English:
Find the number of natural solutions (x≥1, y≥1) of the inequality x²+y² < n, where 0 < n < 2147483647. For example, for n=10 there are 4 solutions: (1,1), (1,2), (2,1), (2,2).
Input
In the first line of input the number of test cases k is given. In the next k lines, there are the n values given.
Output
In the output, you have to display in separate lines the number of natural solutions of the inequality.
Example
Input:
2
10
11
Output:
4
6
Your solution seems fast already. The main possibility to reduce the time spent is to suppress the call to sqrtin the loop. This is obtained by considering that the value a = sqrt(n - (i * i)) does not vary very much from one iteration to the next one.
Here is the code:
r = 0;
p = sqrt(n);
if ((p*p) == n) p--;
a = p;
for (long long i = 1; i <= p; i++)
{
while ((n-i*i) <= a*a) {
--a;
}
r += a;
}

Maximum value of M digits out of N digits [duplicate]

This question already has answers here:
How to get the least number after deleting k digits from the input number
(11 answers)
Closed 6 years ago.
I am trying to code a program that can do something like this:
in:
5 4
1 9 9 9 0
out:
9990
and i have a problem. It doesnt work on any set of numbers. For example it works for the one above, but it doesnt work for this one:
in:
15 9
2 9 3 6 5 8 8 8 8 7 2 2 8 1 4
out: 988887814
2 9 3 6 5 8 8 8 8 7 2 2 8 1 4
I did this with a vector approach and it works for any set of numbers, but i'm trying to do it a stack for a better complexity.
EDIT ---- MODIFIED FOR STD::STACK
Code for method using stack:
#include <iostream>
#include <fstream>
#include <stack>
using namespace std;
ifstream in("trompeta.in");
ofstream out("trompeta.out");
void reverseStack(stack<char> st) {
if(!st.empty())
{
char x = st.top();
st.pop();
reverseStack(st);
out<<x;
}
return;
}
int main()
{
int n,m,count=1;
stack <char> st;
char x;
in>>n>>m;
in>>x;
st.push(x);
for(int i=1; i<n; i++)
{
in>>x;
if(st.top()<x && count+n-i-1>=m)
{
st.pop();
st.push(x);
}
else
{
st.push(x);
count++;
if (count>m-1) break;
}
};
reverseStack(st);
}
Code for method using vectors:
#include <iostream>
#include <fstream>
using namespace std;
ifstream in ( "trompeta.in" );
ofstream out ( "trompeta.out" );
int main ()
{
int i = 0, N, M, max, j, p = 0, var;
in >> N >> M;
char* v = new char[N];
char* a = new char[M];
in >> v;
var = M;
max = v[0];
for ( i = 0; i < M; i++ )
{
for ( j = p ; j < N-var+1; j++ )
{
if ( v[j] > max )
{
max = v[j];
p = j;
}
}
var--;
a[i] = max;
max = v[p+1];
p = p+1;
}
for ( i = 0; i < M; i++ )
out << a[i]-'0';
}
Can any1 help me to get the STACK code working?
Using the fact that the most significant digit completely trumps all other digets except in place of a tie, I would look at the first (N-M+1) digits, find the largest single digit in that range.
If it occurs once, the first digit is locked in. Discard the digits which occur prior to that position, and you repeat for "maximum value of M-1 numbers of out N-position" to find the remaining digits of the answer. (or N-position-1, if position is zero based)
If it occurs multiple times, then recursively find "maximum value of M-1 numbers out of N-position" for each, then select the largest single result from these. There can be at most N such matches.
I forgot to mention, if N==M, you are also done.
proof of recursion:
Computing the value of the sub-match will always select M-1 digits. When M is 1, you only need to select the largest of a few positions, and have no more recursion. This is true for both cases. Also the "select from" steps always contain no more than N choices, because they are always based on selecting one most significant digit.
------------------ how you might do it with a stack ----------------
An actual implementation using a stack would be based on an object which contains the entire state of the problem, at each step, like so:
struct data { // require: n == digits.size()
int n, m;
std::string digits;
bool operator<(const data &rhs){ return digits < rhs.digits; }
};
The point of this is not just to store the original problem, but to have a way to represent any subproblem, which you can push and pop on a stack. The stack itself is not really important, here, because it is used to pick the one best result within a specific layer. Recursion handles most of the work.
Here is the top level function which hides the data struct:
std::string select_ordered_max(int n, int m, std::string digits) {
if (n < m || (int)digits.size() != n)
return "size wrong";
data d{ n, m, digits };
data answer = select_ordered_max(d);
return answer.digits;
}
and a rough pseudocode of the recursive workhorse
data select_ordered_max(data original){
// check trivial return conditions
// determine char most_significant
// push all subproblems that satisfy most_significant
//(special case where m==1)
// pop subproblems, remembering best
return answer {original.m, original.m, std::string(1, most_significant) + best_submatch.digits };
}
String comparison works on numbers when you only compare strings of the exact same length, which is the case here.
Yes, I know having n and m is redundant with digits.size(), but I didn't want to work too hard. Including it twice simplified some recursion checks. The actual implementation only pushed a candidate to the stack if it passed the max digit check for that level of recursion. This allowed me to get the correct 9 digit answer from 15 digits of input with only 28 candidates pushed to the stack (and them popped during max-select).
Now your code has quite a few issues, but rather than focusing on those lets answer the question. Let's say that your code has been corrected to give us:
const size_t M where M is the number of digits expected in our output
const vector<int> v which is the input set of numbers of size N
You just always want to pick the highest value most significant number remaining. So we'll keep an end iterator to prevent us from picking a digit that wouldn't leave us with enough digits to finish the number, and use max_element to select:
const int pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
auto maximum = 0;
auto end = prev(cend(v), M - 1);
auto it = max_element(cbegin(v), end);
for (auto i = M - 1; i > 0; --i) {
maximum += *it * pow10[i];
advance(end, 1);
it = max_element(next(it), end);
}
maximum += *it;
Live Example
This code depends upon M being greater than 0 and less than N and less than log10(numeric_limits<int>::max())
EDIT: Sad to say this solves the consecutive digits problem, after edits the question wants subsequent digits, but not necessarily consecutive
So the little known numeric library provides inner_product which seems like just the tool for this job. Now your code has quite a few issues, but rather than focusing on those lets answer the question. Let's say that your code has been corrected to give us:
vector<int> foo(M) where M is the number of digits expected in our output
const vector<int> v which is the input set of numbers of size N
We'll use foo in the inner_product, initializing it with decreasing powers of 10:
generate(begin(foo), end(foo), [i=int{1}]() mutable {
auto result = i;
i *= 10;
return result; });
We can then use this in a loop:
auto maximum = 0;
for (auto it = prev(rend(v), size(foo) + 1); it != rbegin(v); advance(it, -1)) {
maximum = max<int>(inner_product(cbegin(foo), cend(foo), it, 0), maximum);
}
maximum = max<int>(inner_product(cbegin(foo), cend(foo), rbegin(v), 0), maximum);
Live Example
To use it's initialization requires that your initial M was smaller than N, so you may want to assert that or something.
--EDITED--
here's my suggestion with STACK based on my previous suggestion using vector
findMaxValueOutOfNDigits(stackInput, M, N)
{
// stackInput = [2, 9, 3, 6, 5, 8, 8, 8, 8, 7, 2, 2, 8, 1, 4]
// *where 4 was the first element to be inserted and 2 was the last to be inserted
// if the sequence is inverted, you can quickly fix it by doing a "for x = 0; x < stack.length; x++ { newStack.push(stack.pop()) }"
currentMaxValue = 0
for i = 0; i < (M - N + 1); i++
{
tempValue = process(stackInput, M, N)
stackInput.pop()
if (tempValue > currentMaxValue)
currentMaxValue = tempValue
}
return currentMaxValue
}
process(stackInput, M, N)
{
tempValue = stackInput.pop() * 10^(N - 1)
*howManyItemsCanILook = (M - N + 1)
for y = (N - 2); y == 0; y++
{
currentHowManyItemsCanILook = *howManyItemsCanILook
tempValue = tempValue + getValue(stackInput, *howManyItemsCanILook) * 10^(y)
*howManyItemsCanILook = *howManyItemsCanILook - 1
for x = 0; x < (currentHowManyItemsCanILook - *howManyItemsCanILook); x++
{
stackInput.pop()
}
}
return tempValue
}
getValue(stackInput, *howManyItemsCanILook)
{
currentMaxValue = stackInput.pop()
if (currentMaxValue == 9)
return 9
else
{
goUntil = *howManyItemsCanILook
for i = 0; i < goUntil; i++
{
*howManyItemsCanILook = *howManyItemsCanILook - 1
tempValue = stackInput.pop()
if (currentMaxValue < tempValue)
{
currentMaxValue = tempValue
if (currentMaxValue == 9)
return currentMaxValue
}
}
return currentMaxValue
}
}
note: where *howManyItemsCanILook is passed by reference
I hope this helps

SIGSEGV Error in Simple Dynamic Programming on SPOJ

I am just beginning with dynamic programming, and I have just attempted a simple question based on DP, on Spoj. Link - http://www.spoj.com/problems/MST1/
Here is the question statement -
On a positive integer, you can perform any one of the following 3
steps.
1.) Subtract 1 from it. ( n = n - 1 )
2.) If its divisible by 2, divide by 2. ( if n % 2 == 0 , then n = n / 2 )
3.) If its divisible by 3, divide by 3. ( if n % 3 == 0 , then n = n / 3 )
Given a positive integer n and you task is find the minimum number of
steps that takes n to one.
Input:
The input contains an integer T (1 ≤ T ≤ 100) number of test cases.
Second line input is N (0 < N ≤ 2*10^7 ) that indicates the positive
number.
Output:
For each case, print the case number and minimum steps.
Here's my code -
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
// Memo Function returns the smallest number of steps possible for integer a
int memo(int a, int mem[]);
int mem[20000010];
int main() {
int t;
scanf("%i", &t);
for(int i = 1; i <= t; i++) {
int n;
scanf("%i", &n);
memset(mem, -1, sizeof(mem));
mem[1] = 0;
printf("Case %i: %i\n", i, memo(n, mem));
}
return 0;
}
int memo(int a, int mem[]) {
if (mem[a] != -1) return mem[a]; // If the value of smallest steps have already been calculated
int r; // Current Lowest number of steps
r = memo(a - 1, mem) + 1;
if (a % 2 == 0) r = min(r, memo(a/2, mem) + 1);
if (a % 3 == 0) r = min(r, memo(a/3, mem) + 1);
mem[a] = r;
return r;
}
I have looked up this error on the internet and here on StackOverflow, and I have found that it may occur when we are trying to access the memory that has not been allocated, for example accessing the 11th element of a 10 element array. But I don't think that's the case here.
Also, I think the upper limit of the question is 2*10^7, also the array is global, so it shouldn't be an issue. Maybe there's some issue in the way I am using the memset function? I really don't know!
Any help will be appreciated! Thanks for reading!
Your DP idea is correct but your code is not working for a large inputs (e.g. 1x10^6, or the upper boundary, 2x10^7).
By changing your code a little, you can pre-compute every answer and then output only the ones you are interested in. It will be not very time-consuming because of the dynamic programming fashion of the problem, i.e., a complex problem can be solved as a combination of one or more previously solved problems.
int main()
{
// Initialize DP array
memset(mem, -1, sizeof(mem));
mem[1] = 0;
// Pre-compute every possible answer
for(int i = 2; i <= 20000000; i++)
mem[i] = memo(i);
// Read the number of test cases
int t;
scanf("%d", &t);
// Print only the desired answer, ie, mem[n]
for(int i = 1; i <= t; i++) {
int n;
scanf("%d", &n);
printf("Case %d: %d\n", i, mem[n]);
}
return 0;
}
I got an ACCEPTED with this approach.
Another tip: since your DP array is global, you do not have to pass it to the DP function every time.

How to make this algorithm faster? [closed]

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 am trying to come up with the following algorithm:
The input is unsigned integer number.
The output is the size of the array of unordered pairs of unsigned integers, which, when multiplied, give a number less then or equal to the input.
I have one naive implementation working, but it is way too slow for my purpose (compl. O(n^2), please correct me if I am wrong). My question is: how to make it faster?
#include <iostream>
using namespace std;
bool notInYet(int t[][1], int mi, int ma, int m) {
bool val = true;
for(int i = 0; i < m; i++)
if(t[i][0] == mi && t[i][1] == ma)
val = false;
return val;
}
int main() {
int n, m;
int t[100000][1];
cin >> n;
m = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j*i <= n && j <= i; j++) {
if(notInYet(t, j, i, m)) {
t[m][0] = j;
t[m][1] = i;
//cout << "t[" << m << "] = (" << t[m][0] << ", " << t[m][1] << ")" << endl;
m++;
}
}
}
cout << m << endl;
return 0;
}
I think it should be something like that - pseudocode:
int counter = 0;
for int i = 1 to sqrt(input), i++ {
if (input % i == 0) counter++;
}
counter is an answer if you need unique pairs, otherwise you need to multiply it by 2 (and sub 1 if input % sqrt(input) == 0)
If I'm reading correctly #jauser's algorithm doesn't get what you want.
If the target is 5, then the pairs are (1,1)(1,2)(1,3)(1,4)(1,5)(2,2). So the answer is 6. His algorithm will produce 1 because 5 mod 1 == 0, but not mod 2.
In general, if the target is n, then you know (1,k) is a counted pair for all k from 1 to n. There are n - 1 + 1 = n of these. Now you have (2,k) for k from 2 to floor(n/2) (skip 1 because your pairs are unordered). There are n/2-2+1 of these. Continue this through (j,k) for j= floor(sqrt(n)). Putting this is pseudocode
count = 0;
for j in 1 .. floor(sqrt(n))
count += floor(n / j) - j + 1;
Maybe there is even some clever series solution that gets this to a constant time calculation.
Am I missing something in the problem?
Well, you are spending a lot of time effectively calculating the following per i:
j= n/i;
So if you just do that you reduce the complexity to O(n). You can halve it also since the list will contain both (i, j) and (j, i) when i!=j, but that won't reduce the overall complexity.

run time error - non zero exception

my programming teacher gave me this problem to code it in c :
given array of N integers A and a number K. During a turn the maximal value over all Ai is chosen, let's call it MAX. Then Ai =
MAX - Ai is done for every 1 <= i <= N. Help Roman to find out how will the array look like after K turns.
Input
The numbers N and K are given in the first line of an input. Then N integers are given in the second line which denote the array A.
Output
Output N numbers on a single line. It should be the array A after K turns.
Constraints
* 1 <= N <= 10^5
* 0 <= K <= 10^9
* Ai does not exceed 2 * 10^9 by it's absolute value.
Example
Input:
4 1
5 -1 7 0
Output:
2 8 0 7
and my code to this problem is :
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
long int Max(long int *arr, int low, int high)
{
long int max,i;
max = arr[low];
for(i=0;i<=high;i++)
{
if(max<=arr[i])
max = arr[i];
}
return max;
}
/* Driver program to test above function */
int main()
{
long int max,*arr;
long int n,k,c1,c2,c3,i,j;
c1 = (long int)pow(10,5);
c2 = (long int)pow(10,9);
c3 = 2*c2;
scanf("%ld %ld",&n,&k);
if(n<1||n>c1)
exit(1);
else if(k<0||k>c2)
exit(1);
else
{
arr = (long int *)malloc(sizeof(int)*n);
for(i=0;i<n;i++)
{
scanf("%ld",&arr[i]);
if(abs(arr[i])>c3)
exit(1);
}
if(k%2 == 0)
{
for(i=0;i<2;i++)
{
max = Max(arr, 0, n-1);
for(j=0;j<n;j++)
{
arr[j] = max-arr[j];
if(abs(arr[j])>c3)
exit(1);
}
}
}
else if(k%2 != 0)
{
max = Max(arr, 0, n-1);
for(j=0;j<n;j++)
{
arr[j] = max-arr[j];
/*if(abs(arr[j])>c3)
exit(1);*/
}
}
/* for(m=0;m<n;m++)
printf("%ld ",arr[m]);
printf("\n");*/
for(i=0;i<n;i++)
printf("%ld ",arr[i]);
printf("\n");
}
return 0;
}
i executed this code on gcc compiler in ubuntu, it is working perfectly with all the constraints satisfied but when I uploaded this code on my teacher's portal which has a compiler and executed the code, it said Runtime error -
nzec which means a non-zero exception which is used to signify that main() does not have "return 0;" statement or exception thrown by c++ compiler.
Please, can anyone help me what is wrong in my code as there is a return 0; statement in my code. Please Help.
Everyone has pointed out multiple use of exits ... Can I reduce them using any other way in place of exit()?
My guess is that it has to do with the various exit(1) statements you have for error conditions.
As pointed out by Dave Costa, exit(1) could be the cause
Another possible problem is the size of the allocated array:
arr = (long int *)malloc(sizeof(int)*n);
should be:
arr = malloc(sizeof(long int)*n);
And note that you don't need to use pow for constants:
c1 = (long int)pow(10,5);
c2 = (long int)pow(10,9);
could be replaced with:
c1 = 1e5L;
c2 = 1e9L;