SHORT How should I reduce (optimize) the number of needed operations in my code?
LONGER For research, I programmed a set of a equations in C++ to output a sequence if it fits the model. On the very inside of the code is this function, called MANY times during run-time:
int Weight(int i, int q, int d){
int j, sum = 0;
if (i <= 0)
return 0;
else if (i == 1)
return 1;
for (j = 1; j <= d; j++){
sum += Weight((i - j), q, d);
}
sum = 1 + ((q - 1) * sum);
return sum;
}
So based on the size of variable d, the size of the index i, and how many times this function is called in the rest of the code, many redundant calculations are done. How should I go about reducing the number of calculations?
Ideally, for example, after Weight(5, 3, 1) is calculated, how would I tell the computer to substitute in its value rather than recalculate its value when I call for Weight(6, 3, 1), given that the function is defined recursively?
Would multidimensional vectors work in this case to store the values? Should I just print the values to a file to be read off? I have yet to encounter an overflow with the input sizes I'm giving it, but would a tail-recursion help optimize it?
Note: I am still learning how to program, and I'm amazed I was even able to get the model right in the first place.
You may use memoization
int WeightImpl(int i, int q, int d); // forward declaration
// Use memoization and use `WeightImpl` for the real computation
int Weight(int i, int q, int d){
static std::map<std::tuple<int, int, int>, int> memo;
auto it = memo.find(std::make_tuple(i, q, d));
if (it != memo.end()) {
return it->second;
}
const int res = WeightImpl(i, q, d);
memo[std::make_tuple(i, q, d)] = res;
return res;
}
// Do the real computation
int WeightImpl(int i, int q, int d){
int j, sum = 0;
if (i <= 0)
return 0;
else if (i == 1)
return 1;
for (j = 1; j <= d; j++){
sum += Weight((i - j), q, d); // Call the memoize version to save intermediate result
}
sum = 1 + ((q - 1) * sum);
return sum;
}
Live Demo
Note: As you use recursive call, you have to be cautious with which version to call to really memoize each intermediate computation. I mean that the recursive function should be modified to not call itself but the memoize version of the function. For non-recursive function, memoization can be done without modification of the real function.
You could use an array to store the intermediate values. For example, for certain d and q have an array that contains the value of Weight(i, q, d) at index i.
If you initialize the array items at -1 you can then do in your function for example
if(sum_array[i] != -1){ // if the value is pre-calculated
sum += sum_array[i];
}
else{
sum += Weight((i - j), q, d);
}
Related
The question asks me to find the greatest power devisor of (number, d) I found that the function will be like that:
number % d^x ==0
I've done so far using for loop:
int gratestDevisor(int num, int d){
int p = 0;
for(int i=0; i<=num; i++){
//num % d^i ==0
if( (num % (int)pow(d,i))==0 )
p=i;
}
return p;
}
I've tried so much converting my code to recursion, I can't imagine how to do it and I'm totally confused with recursion. could you give me a tip please, I'm not asking you to solve it for me, just some tip on how to convert it to recursion would be fine.
Here is a simple method with recursion. If ddivides num, you simply have to add 1 to the count, and divide num by d.
#include <stdio.h>
int greatestDevisor(int num, int d){
if (num%d) return 0;
return 1 + greatestDevisor (num/d, d);
}
int main() {
int num = 48;
int d = 2;
int ans = greatestDevisor (num, d);
printf ("%d\n", ans);
return 0;
}
A recursive function consist of one (or more) base case(es) and one (or more) calls to the function itself. The key insight is that each recursive call reduces the problem to something smaller till the base case(es) are reached. State (like partial solutions) are either carried in arguments and return value.
You asked for a hint so I am explicitly not providing a solution. Others have.
Recursive version (which sucks):
int powerDividing(int x, int y)
{
if (x % y) return 0;
return 1 + powerDividing(x/y, y);
}
So, I am trying to solve the problem: http://codeforces.com/contest/448/problem/D
Bizon the Champion isn't just charming, he also is very smart.
While some of us were learning the multiplication table, Bizon the Champion had fun in his own manner. Bizon the Champion painted an n × m multiplication table, where the element on the intersection of the i-th row and j-th column equals i·j (the rows and columns of the table are numbered starting from 1). Then he was asked: what number in the table is the k-th largest number? Bizon the Champion always answered correctly and immediately. Can you repeat his success?
Consider the given multiplication table. If you write out all n·m numbers from the table in the non-decreasing order, then the k-th number you write out is called the k-th largest number.
Input
The single line contains integers n, m and k (1 ≤ n, m ≤ 5·105; 1 ≤ k ≤ n·m).
Output
Print the k-th largest number in a n × m multiplication table.
What I did was, I applied binary search from 1 to n*m looking for the number which has exactly k elements less than it. For this, I made the following code:
using namespace std;
#define ll long long
#define pb push_back
#define mp make_pair
ll n,m;
int f (int val);
int min (int a, int b);
int main (void)
{
int k;
cin>>n>>m>>k;
int ind = k;
ll low = 1LL;
ll high = n*m;
int ans;
while (low <= high)
{
ll mid = low + (high-low)/2;
if (f(mid) == k)
ans = mid;
else if (f(mid) < k)
low = mid+1;
else
high = mid-1;
}
cout<<ans<<"\n";
return 0;
}
int f (int val)
{
int ret = 0;
for ( int i = 1; i <= n; i++ )
{
ret = ret + min(val/i,m);
}
return ret;
}
int min (int a, int b)
{
if (a < b)
return a;
else
return b;
}
However, I don't know why but this gives wrong answer on test cases:
input
2 2 2
output
2
My output comes out to be 0
I am learning binary search but I don't know where am I going wrong with this implementation. Any help will be appreciated.
Ignoring the fact that your binary search is not the fastest method, you still want to know why it is incorrect.
First be very clear about what you want and what your f is returning:
looking for the number which has exactly k elements less than it.
No! You are looking for the smallest number that has k elements less than or equal to it. And your function f(X) returns the count of elements less than or equal to X.
So when f(X) returns a value too small, you know X must be larger by at least 1, so low=mid+1 is correct. But when f(X) returns a value too large, X might be perfect (might be an element appearing several times in the table). Conversely, when f(X) returns exactly the right number, X might still be too big (X might be a value that appears zero times in the table).
So when f(X) is not too small, the best you can do is high=mid not high=mid-1
while (low < high)
{
ll mid = low + (high-low)/2;
if (f(mid) < k)
low = mid+1;
else
high = mid;
}
Notice low never gets > high, so stop when they are equal, and we don't try to catch the ans along the way. Instead at the end low==high==Answer
The contest says 1 second time limit. On my computer, your code with that correction solves the max size problem in under a second. But I'm not sure the judging computer is that fast.
Edit: int is too small for the max size of the problem, so you can't return int from f:
n, m, and i each fit in 32 bits, but the input and output of f() as well as k, ret, low and high all need to hold integers up to 2.5e11
import java.util.*;
public class op {
static int n,m;
static long k;
public static void main(String args[]){
Scanner s=new Scanner(System.in);
n=s.nextInt();
m=s.nextInt();
k=s.nextLong();
long start=1;
long end=n*m;
long ans=0;
while(end>=start){
long mid=start+end;
mid/=2;
long fmid=f(mid);
long gmid=g(mid);
if(fmid>=k && fmid-gmid<k){
ans=mid;
break;
}
else if(f(mid)>k){
end=mid-1;
}
else{
start=mid+1;
}
}
System.out.println(ans);
}
static long f (long val)
{
long ret = 0;
for ( int i = 1; i <= n; i++ )
{
ret = ret + Math.min(val/i,m);
}
return ret;
}
static long g (long val)
{
long ret = 0;
for ( int i = 1; i <= n; i++ )
{
if(val%i==0 && val/i<=m){
ret++;
}
}
return ret;
}
public static class Pair{
int x,y;
Pair(int a,int b){
x=a;y=b;
}
}
}
P = (10^9 + 7)
Choose(m, n) = m! / (n! * (m - n)!)
I want to calculate the value of Choose(m, n) mod P for large m and n.
How can I do that in C++ ?
This is what I use as it has a fairly good range without too much intermediate overflow. However C(n,k) gets big fast, it is O(n^k) after all.
size_t N_choose_K(size_t n, size_t k)
{
size_t numer = 1;
size_t denom = 1;
if (k > n - k) {
k = n - k;
}
while (k > 0) {
numer *= n;
denom *= k;
--n; --k;
}
return numer / denom;
}
EDIT: Assumes you need integral results. You can move to floating point results and get more range if you need it and can stand to lose the accuracy.
You can use the fact that multiplication is closed under Zp meaning that: a b mod p = (a mod p) (b mod p) mod p. Using this theorem, one can calculate ab mod p effectively (for instance, this Python implementation.
Next we can make use of Euler's theorem saying: a-1 mod p=a(p-2) mod p.
Now that we know these facts, we can come up with an effective solution: first we multiply over all elements in the numerator, this is thus a range from k+1 (inclusive) to n, and since this is a multiplication, we can always perform a modulo:
long long numerator(int n, int k, int p) {
long long l = 1;
for(int j = k+1; j <= n; j++) {
l = (l*j)%p;
}
return l;
}
Now we still need to divide it by (n-k)!. We can do this by first calculating (n-k)! mod p like we already did in the previous code fragment:
long long denominator(int n, int k, int p) {
long l = 1;
for(int j = 2; j <= n-k; j++) {
l = (l*j)%p;
}
return l;
}
Now in order to divide it, we can use Euler's theorem on the result of denominator. Therefore we first implement the pow function with modulo:
long long pow(long long a, int k, int p) {
if(k == 0) {
return 1;
}
long long r = pow((a*a)%p,k>>0x01,p);
if((k&0x01) == 0x01) {//odd number
r = (r*a)%p;
}
return r;
}
Now we can merge these together like:
long long N_choose_K(int n, int k, int p) {
long long num = numerator(n,k,p);
long long den = denominator(n,k,p);
return (num*pow(den,p-2,p))%p;
}
So what you basically do is you determine the numerator num in Zp, the value of the denominator den in Zp, and then you use Euler's theorem to find the inverse of the denominator in Zp, such that you can multiply and perform the last modulo operation. Then you can return it.
I'm writing a recursion function to find the power of a number and it seems to be compiling but doesn't output anything.
#include <iostream>
using namespace std;
int stepem(int n, int k);
int main()
{
int x, y;
cin >> x >> y;
cout << stepem(x, y) << endl;
return 0;
}
int stepem(int n, int k)
{
if (n == 0)
return 1;
else if (n == 1)
return 1;
else
return n * stepem(n, k-1);
}
I tried debugging it, and it says the problem is on this line :
return n * stepem(n, k-1);
k seems to be getting some weird values, but I can't figure out why?
You should be checking the exponent k, not the number itself which never changes.
int rPow(int n, int k) {
if (k <= 0) return 1;
return n * rPow(n, --k);
}
Your k is getting weird values because you will keep computing until you run out of memory basically, you will create many stack frames with k going to "-infinity" (hypothetically).
That said, it is theoretically possible for the compiler to give you a warning that it will never terminate - in this particular scenario. However, it is naturally impossible to solve this in general (look up the Halting problem).
Your algorithm is wrong:
int stepem(int n, int k)
{
if (k == 0) // should be k, not n!
return 1;
else if (k == 1) // this condition is wrong
return 1;
else
return n * stepem(n, k-1);
}
If you call it with stepem(2, 3) (for example), you'll get 2 * 2 * 1 instead of 2 * 2 * 2 * 1. You don't need the else-if condition:
int stepem(int n, unsigned int k) // unless you want to deal with floating point numbers, make your power unsigned
{
if (k == 0)
return 1;
return n * stepem(n, k-1);
}
Didn't test it but I guess it should give you what you want and it is tail recursive.
int stepemi(int result, int i int k) {
if (k == 0 && result == i)
return 1;
else if (k == 0)
return result;
else
return stepem(result * i, i, k-1);
}
int stepem(int n, int k) {
return stepemi(n, n, k);
}
The big difference between this piece of code and the other example is that my version could get optimized for tail recursive calls. It means that when you call stepemi recursively, it doesn't have to keep anything in memory. As you can see, it could replace the variable in the current stack frame without having to create a new one. No variable as to remain in memory to compute the next recursion.
If you can have optimized tail recursive calls, it also means that the function will used a fixed amount of memory. It will never need more than 3 ints.
On the other hand, the code you wrote at first creates a tree of stackframe waiting to return. Each recursion will add up to the next one.
Well, just to post an answer according to my comment (seems I missed adding a comment and not a response :-D). I think, mainly, you have two errors: you're checking n instead of k and you're returning 1 when power is 1, instead of returning n. I think that stepem function should look like:
Edit: Updated to support negative exponents by #ZacHowland suggestion
float stepem(int n, int k)
{
if (k == 0)
return 1;
else
return (k<0) ?((float) 1/n) * stepem(n, k+1) :n * stepem(n, k-1);
}
// Power.cpp : Defines the entry point for the console application.
//
#include <stream>
using namespace std;
int power(int n, int k);
void main()
{
int x,y;
cin >>x>>y;
cout<<power(x,y)<<endl;
}
int power(int n, int k)
{
if (k==0)
return 1;
else if(k==1) // This condition is working :) //
return n;
else
return n*power(n,k-1);
}
your Program is wrong and it Does not support negative value given by user,
check this one
int power(int n, int k){
'if(k==0)
return 1;
else if(k<0)
return ((x*power(x,y+1))*(-1));
else
return n*power(n,k-1);
}
sorry i changed your variable names
but i hope you will understand;
#include <iostream>
using namespace std;
double power(double , int);// it should be double because you also need to handle negative powers which may cause fractions
int main()
{
cout<<"please enter the number to be powered up\n";
double number;
cin>>number;
cout<<"please enter the number to be powered up\n";
int pow;
cin>>pow;
double result = power(number, pow);
cout<<"answer is "<<result <<endl;
}
double power( double x, int n)
{
if (n==0)
return 1;
if (n>=1)
/*this will work OK even when n==1 no need to put additional condition as n==1
according to calculation it will show x as previous condition will force it to be x;
try to make pseudo code on your note book you will understand what i really mean*/
if (n<0)
return x*power(x, n-1);
return 1/x*power(x, n+1);// this will handle negative power as you should know how negative powers are handled in maths
}
int stepem(int n, int k)
{
if (k == 0) //not n cause you have to vary y i.e k if you want to find x^y
return 1;
else if (k == 1)
return n; //x^1=x,so when k=1 it should be x i.e n
else
return n * stepem(n, k-1);
}
i am a bit confused in using array in doing recursion, can anyone correct my mistake?
new update, based on question required some of the line cannot be edit
double sum_of_array(double x[],int size)
{
static double sum; <---can be edit
int index = 0; <--can be edit
if(index<size){
return sum + sum_of_array(x,size-1); <--can be edit
} else {
something ; <--can be edit
return sum; <--can be edit
}
}
int main(void){
double x[] = {4.5,5.0,6.8};
double y[] = {4.7,3.4,2.5,5.2};
cout<<"Sum X = "<<sum_of_array(x,3)<<endl;
cout<<"Sum Y = "<<sum_of_array(y,4)<<endl;
return 0;
}
output:
Sum of the element in X[]=15.3
Sum of the element in Y[]= 15.8
You're trying to craft something extremely overengineered. You need two things - an edge case (recursion cut-off) and a general case (descend in recursion). In your case the edge case is "array size is zero" and the general case is "grab the first element and pass the rest of array into recursion".
It could be something like this:
double sum_of_array( double x[], int size )
{
if( size == 0 ) { //this is the edge case
return 0;
}
// here you grab the first element and pass the rest of array into a recursive call
return x[0] + sum_of_array( x + 1, size - 1 );
}
There are quite some errors in this code:
First, the constant sum seems to be useless. What is ever used for?
Second, you never take the contents of x in your function.
The logic of your recursive function is just wrong. You never actually read the contents of the array. I'm surprised you got any meaningful output out of that.
You need to rethink of the recursive definition to perform this addition.
Base case(s):
Sum of an empty array is 0..
i.e., sum_of_array(x, 0) == 0.
Sum of a 1-element array is the value of the element.
i.e., sum_of_array(x, 1) == x[0]
Recursive case:
Sum of an n-element array is the sum of the nth element and the sum of the first n-1 elements.
i.e., sum_of_array(x, n) == x[n-1] + sum_of_array(x, n-1)
Figure out how to encode this logic in your function.
You never actually add the values in x[] and y[] to sum and in addition, index is always equal to 0. You should probably pass it as another parameter to the function:
double sum_of_array(double x[], int size, int index)
{
if(index<size){
return x[index] + sum_of_array(x, size, index+1);
}
else {
return 0;
}
}
You don't actually need the sum variable.
The problem is that you are using a static variable sum instead of x[size - 1]. Showing how to fix this is redundant at this moment (7 answers already do this). However, this can be done in one line with built in c++ capabilities:
#include <algorithm>
double sum_of_array(double x[], int size)
{
return std::accumulate(x, x + size, 0.);
}
Error is you did not initialized static variable sum.
I'd start with this:
return sum + sum_of_array(x,size-1);
Shouldn't you be returning:
return x[size] + sum_of_array(x,size-1);
Besides this, you should find a way to set sum to zero between initial calls to the function, because otherwise it will accumulate the sum of all the arrays you attempt to sum up.
The point is, you never initialize sum, so it has some sort of garbage there.
Whose idea was it to use a recursion of all things when a simple for loop would do the trick? Is this homework?
double sum_of_array(double x[],int size)
{
size = size - 1;
if(size < 0){
return 0;
}
return x[size] + sum_of_array(x, size);
}
Ok then it should be like this:
double sum_of_array(double x[],int index)
{
int size = sizeof( x) / sizeof( x[0] );
if(index<size){
return x[index] + sum_of_array(x, index + 1);
}
return 0;
}
then call
sum_of_array(x,0);
IE you always call the first time with 0 as the index
Ok last attempt:
double sum_of_array(double x[], int index, int size)
{
if(index < size){
return x[index] + sum_of_array(x, index + 1, size);
}
else {
return 0;
}
}
then
cout<<"Sum X = "<<sum_of_array(x,0,3)<<endl;
This is how I've done it:
double sum_of_array(double x[], int size)
{
if(size == 0){
return 0;
}
else{
return x[--size] + sum_of_array(x, size);
}
}
I hope I can still chime in with my answer. The most recent answer excluding mine is from 2011.
This is yet another solution to calculate the sum of all elements in an array.
double array_sum(double *p_array, int idx_low, int idx_high){
if(idx_low == idx_high)
return p_array[idx_low];
int idx_mid=idx_low+(idx_high-idx_low)/2;
return array_sum(p_array,idx_low,idx_mid)+array_sum(idx_mid+1, idx_high);
}
Analysis of this algorithm would yeild a run-time of O(n*log(n)).
However, you'd do wise to take this statement with a pinch of salt.