Memory + dynamic programming or recursion - c++

Problem is that i have 64 megabytes on solution,so i can use only 16,777,216 int numbers.
But for answer i must use 33,333,333 numbers,so some answers will not be considered.
Actually, problem is this.
By the way, i had my own code instead:
#include <iostream>
using namespace std;
int sq(int x) {
return (long long)(x*x) %(1000000);
}
int func(int x) {
if (x==0)
return 3;
else {
return ( sq(func(x-1))+2)%(1000000);
}
}
int main()
{
/*const int num=16 777 216;
int* arr=new int [num];
arr[0]=3;
for (int i=1;i<num;i++)
arr[i]=((arr[i-1]%(1000000))*(arr[i-1])%(1000000)+2)%(1000000);*/
int t,rez;
int n;
cin>>t;
for (int p=0;p<t;p++) {
cin>>n;
if (n%3!=0) {
rez=0;
} else {
// rez=arr[n/3-1];
rez=func(n/3-1);
}
cout<<rez<<endl;
}
return 0;
}
In comments there is second solution.
I can do it with recursion, but i have limit in 1 second.
So what code would be OK?

You do not need anywhere near that many entries (10^9 / 3). Note that you need only the values mod 10^6. You have a recurrence relationship among these:
a[n] = a[n-1]^2 + 2
Each value depends only on the previous one, so there will be a simple sequence of numbers. The relation will have a period of no more than 10^6. Since they're all odd, the maximum length is cut in half.
As it turns out, the sequence repeats after 5003 terms, with a period of 5000: 3, 11, 123 do not appear later in the sequence.
So, forget that huge array. Compute the 5003 terms you need. Now for any input number N, you have 3 cases:
(1) N is not divisible by 3: return 0
else N is divisible by 3; call the quotient M
(2) M <= 3: return arr[M]
(3) else, get the needed subscript as m = ((M-3) mod 5000) + 3;
return arr[m]
You can now handle arbitrarily large input.

Related

Given a integer N>0, how many integers in the interval [0, 2^N) have exactly N-1 set bits? Write a short function that returns the correct answer

I wrote some C++ code to solve this problem:
#include <iostream>
#include <cmath>
using namespace std;
unsigned int countSetBits(unsigned int n)
{
int totalCount = 0, i;
int cond = n-1;
for(i=0;i<pow(2,n);i++){
unsigned int count = 0;
while (i) {
count += i & 1;
i >>= 1;
}
if(count == cond){
totalCount++;
}
}
return totalCount;
}
int main()
{
int n=5;
cout<<countSetBits(5);
return 0;
}
Although it is compiling succesfully, it doesn't print anything.
I can't figure out where is the problem...
Pen and paper solution:
N=2 2^N-1 = 0b11 Possible integers with 1 bit set:
01
10
N=3 2^N-1 = 0b111 Possible integers with 2 bits set:
011
101
110
N=4 2^N-1 = 0b1111 Possible integers with 3 bits set:
0111
1011
1101
1110
So, N seems to be the answer.
The problem is that you are modifying the 'control' variable (i) of your for loop inside that loop, so that the value of i will never reach the loop limit and it will run forever.
To fix this, take a copy of the current i value and modify that:
unsigned int countSetBits(unsigned int n)
{
int totalCount = 0, i;
int cond = n - 1;
int limit = pow(2, n); /// Calculate this ONCE, rather than on each loop!
for (i = 0; i < limit; i++) {
unsigned int count = 0;
int j = i; /// Take a copy of i here (otherwise it will keep getting reset to zero)...
while (j) { /// ...and do your test on the copy!
count += j & 1;
j >>= 1;
}
if (count == cond) {
totalCount++;
}
}
return totalCount;
}
There are also other improvements you can make, as mentioned in the comments. But the code changes I have posted at least fix your problem.
You modify i inside the loop. The inner while loop will always make i == 0, no matter what the loop counter is, hence the condition for the for loop will never be false. Use a temporary. Also don't use pow to calculate powers of 2. 2^N is (1 << N).
You need N+1 bits to represent 2^N. (2^N)-1 has the N lower bits set. There are N possible bits to unset in (2^N)-1, hence there are N numbers with N-1 bits set in [0,2^N). qed ;)
unsigned int countSetBits(unsigned int n) { return n; }

Optimizing a recursive function

I'm creating a program that returns the least quantity of sums required to get to a number (n) using only 1, 2, 6 and 13. It works perfectly for small values of n, but once n gets to values like 200 it takes the program too much time to calculate the result.
Therefore, I have two questions:
1. Is there any way to make the recursion faster?
2. Should I avoid using recursion and use a loop instead?
Here's the commented code:
#include <iostream>
#define MAX 500000
using namespace std;
void cal(int inp, int &mini, int counter = 0);
int main (void)
{
//Gets input
int n;
cin >> n;
//Defines mini as the MAX result we can get
int mini = MAX;
//Calls the function
cal(n, mini);
//Prints the best result
cout << mini << endl;
return 0;
}
void cal(int inp, int &mini, int counter)
{
//Breaks recursion if it finds an answer
if(!inp)
{
if(counter<mini) mini = counter;
return;
}
//Breaks recursion if the input is negative
//or the counter is more than the best result
else if((inp<0) || (counter>mini)) return;
//Counts amount of recursions
counter++;
//Tries every combination
cal(inp-13, mini, counter);
cal(inp-6, mini, counter);
cal(inp-2, mini, counter);
cal(inp-1, mini, counter);
return;
}
Thank you
The problem is your brute force. Let me suggest something better:
Preliminaries: If you have two 1s, it is always better to use a 2. If you have three 2s, it is better to use a 6. If you have thirteen 6s, it is better to use six thirteens.
So the any admissable sum will always look like n = 13m+k where k is written as a sum of 1, 2, and 6. With the preliminaries, we know that for the optimal sum k will never exceed 1+2*2+12*6 = 77. (The reverse doesn't hold. Not any number below 78 is best written without 13s of course.) So brute forcing those is good enough. You can then use a lookup table.
This could still be optimized further, but it should not break down at 200.
Assuming you have found your first 77 entries (which can be optimized as well) you can do this (still unoptimized ;-):
int num_13 = ((n-78) / 13) + 1;
int sum_length = MAX;
for (i = num_13; i*13 < n; i++) {
int tmp = entries_77[n-i*13]+i;
if (tmp < sum_length) {
num_13 = i;
sum_length = tmp;
}
}
I would be even quicker to compile an array for the equivalence classes modulo 13, since for any given equivalence class any number exceeding 78 will have the same k.
You can use DP (Dynamic Programming) approach to solve your problem. It's well known Coins Problem
Your recursion needs a memoization to avoid repetitive calculation. And no need for the second and third parameter of the recursion. I have updated and put explanation on your code. Let me know if you have any confusion.
#include <iostream>
#include <string.h>
#define INF 999999
using namespace std;
int cal(int inp);
int mem[502];
int main (void)
{
//Gets input
int n;
cin >> n;
//initialzing the array for using with memoization
memset(mem,-1,sizeof(mem));
//Calls the function
//Prints the best result
cout << cal(n) << endl;
return 0;
}
//returns the minimum quantity of sum operations to get inp.
int cal(int inp)
{
//Breaks recursion if it finds an answer.
//Return cost 0. As in this stage no processing was done.
if(!inp)
return 0;
// Returning infinite cost for invalid case.
if(inp < 0)
return INF;
int _ret = mem[inp];
// If already visited here before then no need to calcuate again.
// Just return previous calculation. This is called memoisation.
// If not visited then _ret would have equal to -1.
if(_ret >=0 )
return _ret;
_ret = INF;
//Tries every combination and takes the minimum cost.
_ret = min(_ret, cal(inp-13)+1);
_ret = min(_ret,cal(inp-6)+1);
_ret = min(_ret,cal(inp-2)+1);
_ret = min(_ret,cal(inp-1)+1);
// Updating the value so that can be used for memoization.
mem[inp] = _ret;
return _ret;
}
This will also work for larger numbers. Complexity is 4*n.

Find Largest Prime Factor - Complexity of Code

I tried a code on a coding website to find the largest prime factor of a number and it's exceeding the time limit for the last test case where probably they are using a large prime number. Can you please help me to reduce the complexity of the following code?
int main()
{
long n;
long int lar, fact;
long int sqroot;
int flag;
cin >> n;
lar=2, fact=2;
sqroot = sqrt(n);
flag = 0;
while(n>1)
{
if((fact > sqroot) && (flag == 0)) //Checking only upto Square Root
{
cout << n << endl;
break;
}
if(n%fact == 0)
{
flag = 1;
lar = fact;
while(n%fact == 0)
n = n/fact;
}
fact++;
}
if(flag == 1) //Don't display if loop fact reached squareroot value
cout << lar << endl;
}
Here I've also taken care of the loop checking till Square Root value. Still, how can I reduce its complexity further?
You can speed things up (if not reduce the complexity) by supplying a hard-coded list of the first N primes to use for the initial values of fact, since using composite values of fact are a waste of time. After that, avoid the obviously composite values of fact (like even numbers).
You can reduce the number of tests by skipping even numbers larger than 2, and stopping sooner if you have found smaller factors. Here is a simpler and faster version:
int main() {
unsigned long long n, lar, fact, sqroot;
cin >> n;
lar = 0;
while (n && n % 2 == 0) {
lar = 2;
n /= 2;
}
fact = 3;
sqroot = sqrt(n);
while (fact <= sqroot) {
if (n % fact == 0) {
lar = fact;
do { n /= fact; } while (n % fact == 0);
sqroot = sqrt(n);
}
fact += 2;
}
if (lar < n)
lar = n;
cout << lar << endl;
return 0;
}
I am not sure how large the input numbers may become, using the larger type unsigned long long for these computations will get you farther than long. Using a precomputed array of primes would help further, but not by a large factor.
The better result I've obtained is using the function below (lpf5()). It's based on the primality() function (below) that uses the formulas 6k+1, 6k-1 to individuate prime numbers. All prime numbers >= 5 may be expressed in one of the forms p=k*6+1 or p=k*6-1 with k>0 (but not all the numbers having such a forms are primes). Developing these formulas we can see a sequence like the following:
k=1 5,7
k=2 11,13
k=3 17,19
k=4 23,25*
k=5 29,31
.
.
.
k=10 59,61
k=11 65*,67
k=12 71,73
...
5,7,11,13,17,19,23,25,29,31,...,59,61,65,67,71,73,...
We observe that the difference between the terms is alternatively 2 and 4. Such a results may be obtained also using simple math. Is obvious that the difference between k*6+1 and k*6-1 is 2. It's simple to note that the difference between k*6+1 and (k+1)*6-1 is 4.
The function primality(x) returns x when x is prime (or 0 - take care) and the first divisor occurs when x is not prime.
I think you may obtain a better result inlining the primality() function inside the lpf5() function.
I've also tried to insert a table with some primes (from 1 to 383 - the primes in the first 128 results of the indicated formulas) inside the primality function, but the speed difference is unappreciable.
Here the code:
#include <stdio.h>
#include <math.h>
typedef long long unsigned int uint64;
uint64 lpf5(uint64 x);
uint64 primality(uint64 x);
uint64 lpf5(uint64 x)
{
uint64 x_=x;
while ( (x_=primality(x))!=x)
x=x/x_;
return x;
}
uint64 primality(uint64 x)
{
uint64 div=7,f=2,q;
if (x<4 || x==5)
return x;
if (!(x&1))
return 2;
if (!(x%3))
return 3;
if (!(x%5))
return 5;
q=sqrt(x);
while(div<=q) {
if (!(x%div)) {
return div;
}
f=6-f;
div+=f;
}
return x;
}
int main(void) {
uint64 x,k;
do {
printf("Input long int: ");
if (scanf("%llu",&x)<1)
break;
printf("Largest Prime Factor: %llu\n",lpf5(x));
} while(x!=0);
return 0;
}

recursive function error: "stack overflow"

I wrote this function that supposed to find smallest positive integer that is divisible by every number 1 through 20. I get "stack overflow error", even though, when I test for numbers 1 through 10, it works just fine.
here is my code:
#include<iostream>
#include<cstdlib>
using namespace std;
// function prototype
int smallPos(int k, int m,int n);
int main(){
printf("the smallest positive number that is divisible by 1 through 20 is %d ", smallPos(1,1,13));
}
int smallPos(int k, int n, int m){
int div=0;
for(int i = n;i<=m;i++) {
if (k%i==0)
div++;
}
if (div==m) {
return k;
} else {
k+=1;
smallPos(k,n,m);
}
}
Why does it happen? The number shouldn't be that big anyway.
Thank you!
The final condition (div == m) will never be true. For div to become equal to m, the number k should be divisible by all of the numbers in range [n,m).
Edit: I've reread the text in the printf() call to understand what the function does. You're looking for the first number divisible by all numbers in the range. If my calculations are correct, this number should be the product of all unique prime factors of the numbers in the range. For the range [1,13] (as per the function call, not the text), this number should be:
30030 = 1 * 2 * 3 * 5 * 7 * 9 * 11 * 13
Now, this means you are going to invoke the function recursively over 30,000 times, which is obviously way too many times for the size of stack you're using (defaults are relatively small). For a range this size, you should really consider writing an iterative function instead.
Edit: here's an iterative version that seems to work.
int smallPos ( int n, int m )
{
int k = 0;
while ( ++k )
{
int count = 0;
for (int i = n; i<=m; i++)
{
if (k%i==0) {
++count;
}
}
if (count == (m-n+1)) {
return k;
}
}
return k;
}
Indeed, the result for smallPos(1,10), the result is 2520. It seems my previous estimate was a lower bound, not a fixed result.
Your smallPos function incurs undefined behaviour since it is not returning a value in all execution paths. You may want to say return smallPos(k,n,m); in the last part (or just return smallPos(k + 1, n, m); in one go).

How to get the digits of a number without converting it to a string/ char array?

How do I get what the digits of a number are in C++ without converting it to strings or character arrays?
The following prints the digits in order of ascending significance (i.e. units, then tens, etc.):
do {
int digit = n % 10;
putchar('0' + digit);
n /= 10;
} while (n > 0);
What about floor(log(number))+1?
With n digits and using base b you can express any number up to pow(b,n)-1. So to get the number of digits of a number x in base b you can use the inverse function of exponentiation: base-b logarithm. To deal with non-integer results you can use the floor()+1 trick.
PS: This works for integers, not for numbers with decimals (in that case you should know what's the precision of the type you are using).
Since everybody is chiming in without knowing the question.
Here is my attempt at futility:
#include <iostream>
template<int D> int getDigit(int val) {return getDigit<D-1>(val/10);}
template<> int getDigit<1>(int val) {return val % 10;}
int main()
{
std::cout << getDigit<5>(1234567) << "\n";
}
I have seen many answers, but they all forgot to use do {...} while() loop, which is actually the canonical way to solve this problem and handle 0 properly.
My solution is based on this one by Naveen.
int n = 0;
std::cin>>n;
std::deque<int> digits;
n = abs(n);
do {
digits.push_front( n % 10);
n /= 10;
} while (n>0);
You want to some thing like this?
int n = 0;
std::cin>>n;
std::deque<int> digits;
if(n == 0)
{
digits.push_front(0);
return 0;
}
n = abs(n);
while(n > 0)
{
digits.push_front( n % 10);
n = n /10;
}
return 0;
Something like this:
int* GetDigits(int num, int * array, int len) {
for (int i = 0; i < len && num != 0; i++) {
array[i] = num % 10;
num /= 10;
}
}
The mod 10's will get you the digits. The div 10s will advance the number.
Integer version is trivial:
int fiGetDigit(const int n, const int k)
{//Get K-th Digit from a Number (zero-based index)
switch(k)
{
case 0:return n%10;
case 1:return n/10%10;
case 2:return n/100%10;
case 3:return n/1000%10;
case 4:return n/10000%10;
case 5:return n/100000%10;
case 6:return n/1000000%10;
case 7:return n/10000000%10;
case 8:return n/100000000%10;
case 9:return n/1000000000%10;
}
return 0;
}
simple recursion:
#include <iostream>
// 0-based index pos
int getDigit (const long number, int pos)
{
return (pos == 0) ? number % 10 : getDigit (number/10, --pos);
}
int main (void) {
std::cout << getDigit (1234567, 4) << "\n";
}
Those solutions are all recursive or iterative. Might a more direct approach be a little more efficient?
Left-to-right:
int getDigit(int from, int index)
{
return (from / (int)pow(10, floor(log10(from)) - index)) % 10;
}
Right-to-left:
int getDigit(int from, int index)
{
return (from / pow(10, index)) % 10;
}
First digit (least significant) = num % 10, second digit = floor(num/10)%10, 3rd digit = floor(num/100)%10. etc
A simple solution would be to use the log 10 of a number. It returns the total digits of the number - 1. It could be fixed by using converting the number to an int.
int(log10(number)) + 1
Use a sequence of mod 10 and div 10 operations (whatever the syntax is in C++) to assign the
digits one at a time to other variables.
In pseudocode
lsd = number mod 10
number = number div 10
next lsd = number mod 10
number = number div 10
etc...
painful! ... but no strings or character arrays.
Not as cool as Martin York's answer, but addressing just an arbitrary a problem:
You can print a positive integer greater than zero rather simply with recursion:
#include <stdio.h>
void print(int x)
{
if (x>0) {
print(x/10);
putchar(x%10 + '0');
}
}
This will print out the least significant digit last.
Years ago, in response to the above questions I would write the following code:
int i2a_old(int n, char *s)
{
char d,*e=s;//init begin pointer
do{*e++='0'+n%10;}while(n/=10);//extract digits
*e--=0;//set end of str_number
int digits=e-s;//calc number of digits
while(s<e)d=*s,*s++=*e,*e--=d;//reverse digits of the number
return digits;//return number of digits
}
I think that the function printf(...) does something like that.
Now I will write this:
int i2a_new(int n, char *s)
{
int digits=n<100000?n<100?n<10?1:2:n<1000?3:n<10000?4:5:n<10000000?n<1000000?6:7:n<100000000?8:n<1000000000?9:10;
char *e=&s[digits];//init end pointer
*e=0;//set end of str_number
do{*--e='0'+n%10;}while(n/=10);//extract digits
return digits;//return number of digits
}
Advantages:
lookup table indipendent;
C,C++,Java,JavaScript,PHP compatible;
get number of digits, min comparisons: 3;
get number of digits, max comparisons: 4;
fast code;
a comparison is very simple and fast: cmp reg, immediate_data --> 1 CPU clock.
Get all the individual digits into something like an array - two variants:
int i2array_BigEndian(int n, char a[11])
{//storing the most significant digit first
int digits=//obtain the number of digits with 3 or 4 comparisons
n<100000?n<100?n<10?1:2:n<1000?3:n<10000?4:5:n<10000000?n<1000000?6:7:n<100000000?8:n<1000000000?9:10;
a+=digits;//init end pointer
do{*--a=n%10;}while(n/=10);//extract digits
return digits;//return number of digits
}
int i2array_LittleEndian(int n, char a[11])
{//storing the least significant digit first
char *p=&a[0];//init running pointer
do{*p++=n%10;}while(n/=10);//extract digits
return p-a;//return number of digits
}