Find the number where the path of two numbers in a binary tree overlap - binary-tree

#include<iostream>
using namespace std;
int binTree(int n, int m){
if(n == m)
return m;
else if(n < m)
return binTree(n, m/2);
else if(n > m)
return binTree(n/2, m);
}
int main(){
int n,m;
cin >> n >> m;
cout << binTree(n, m);
}
However the compiler tells me that "Non-void function does not return a value in all control paths" in my binTree function... I don't see how?

Logically, I understand your point. The compiler is likely determining that you are not closing out with a default else consider removing the initial condition and allowing that to resolve as your default state.
if (n < m)
return binTree(n, m/2);
else if (n > m)
return binTree(n/2, m);
return m

Related

Convert a number m to n using minimum number of given operations

Question:
Given 2 integers N and M. Convert a number N to M using minimum number of given operations.
The operations are:
Square N (N = N^2)
Divide N by a prime integer P if N is divisible by P (N = N / P and N % P == 0)
Contrants:
N, M <= 10^9
Example:
N = 12, M = 18
The minimum operations are:
N /= 2 -> N = 6
N = N^2 -> N = 36
N /= 2 -> N = 18
My take:
I'm trying to use BFS to solve this problem. For each number, the available edges to other numberers are the operations. But it got Time Limit Exceeded. Is there any better way to solve this?
Here is my BFS code:
queue<pair<int,int> > q;
vector<long long> pr;
ll m,n;
bool prime[MAXN+1];
void solve()
{
while (!q.empty())
{
pii x=q.front();
q.pop();
if (x.first==m)
{
cout << x.second;
return;
}
if (x.first==1) continue;
for(ll k:pr)
{
if (k>x.first) break;
if (x.first%k==0) q.push({x.first/k,x.second+1});
}
q.push({x.first*x.first,x.second+1});
}
}
The algorithm uses the decomposition on N and M in prime factors, keeping trace of the corresponding exponents.
If M has a prime factor that N does not have, there is no solution (the code returns -1).
If N has some prime factors that M doesn't have, then the first step is to divide N by these primes.
The corresponding number of operations is the sum of the corresponding exponents.
At this stage, we get two arrays A and B corresponding to the exponents of the common prime factors, for N and M.
It is worth noting that at this stage, the values of the primes involved is not relevant anymore, only the exponents matter.
Then one must determine the minimum number of squares (= multiplications by 2 of the exponents).
The is the smallest k such that A[i] >= 2^k B[i] for all indices i.
The number of multiplications is added to the number of operations only once, as all exponents are multiplied by 2 at the same time.
Last step is to determine, for each pair (a, b) = (A[i], B[i]), the number of subtractions needed to go from a to b, while implementing exactly k multiplications by 2. This is performed with the following rules:
- if (k == 0) f(a, b, k) = a-b
- Else:
- if ((a-1)*2^k >= b: f(a, b, k) = 1 + f(a-1, b, k)
- else: f(a, b, k) = f(2*a, b, k-1)
The complexity is dominated by the decomposition in primes factors: O(sqrt(n))
Code:
This code is rather long, but a great part consists if helper routines needed for debugging and analysis.
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
void print (const std::vector<int> &v, const std::string s = "") {
std::cout << s;
for (auto &x: v) {
std::cout << x << " ";
}
std::cout << std::endl;
}
void print_decomp (int n, const std::vector<int> &primes, const std::vector<int> &mult) {
std::cout << n << " = ";
int k = primes.size();
for (int i = 0; i < k; ++i) {
std::cout << primes[i];
if (mult[i] > 1) std::cout << "^" << mult[i];
std::cout << " ";
}
std::cout << "\n";
}
void prime_decomp (int nn, std::vector<int> &primes, std::vector<int> &mult) {
int n = nn;
if (n <= 1) return;
if (n % 2 == 0) {
primes.push_back(2);
int cpt = 1;
n/= 2;
while (n%2 == 0) {n /= 2; cpt++;}
mult.push_back (cpt);
}
int max_prime = sqrt(n);
int p = 3;
while (p <= max_prime) {
if (n % p == 0) {
primes.push_back(p);
int cpt = 1;
n/= p;
while (n%p == 0) {n /= p; cpt++;}
mult.push_back (cpt);
max_prime = sqrt(n);
}
p += 2;
}
if (n != 1) {
primes.push_back(n);
mult.push_back (1);
}
print_decomp (nn, primes, mult);
}
// Determine the number of subtractions to go from a to b, with exactly k multiplications by 2
int n_sub (int a, int b, int k, int power2) {
if (k == 0){
if (b > a) exit(1);
return a - b;
}
//if (a == 1) return n_sub (2*a, b, k-1, power2/2);
if ((a-1)*power2 >= b) {
return 1 + n_sub(a-1, b, k, power2);
} else {
return n_sub (2*a, b, k-1, power2/2);
}
return 0;
}
// A return of -1 means no possibility
int n_operations (int N, int M) {
int count = 0;
if (N == M) return 0;
if (N == 1) return -1;
std::vector<int> primes_N, primes_M, expon_N, expon_M;
// Prime decomposition
prime_decomp(N, primes_N, expon_N);
prime_decomp (M, primes_M, expon_M);
// Compare decomposition, check if a solution can exist, set up two exponent arrays
std::vector<int> A, B;
int index_A = 0, index_B = 0;
int nA = primes_N.size();
int nB = primes_M.size();
while (true) {
if ((index_A == nA) && (index_B == nB)) {
break;
}
if ((index_A < nA) && (index_B < nB)) {
if (primes_N[index_A] == primes_M[index_B]) {
A.push_back(expon_N[index_A]);
B.push_back(expon_M[index_B]);
index_A++; index_B++;
continue;
}
if (primes_N[index_A] < primes_M[index_B]) {
count += expon_N[index_A];
index_A++;
continue;
}
return -1; // M has a prime that N doesn't have: impossibility to go to M
}
if (index_B != nB) { // impossibility
return -1;
}
for (int i = index_A; i < nA; ++i) {
count += expon_N[i]; // suppression of primes in N not in M
}
break;
}
std::cout << "1st step, count = " << count << "\n";
print (A, "exponents of N: ");
print (B, "exponents of M: ");
// Determination of the number of multiplications by two of the exponents (= number of squares)
int n = A.size();
int n_mult2 = 0;
int power2 = 1;
for (int i = 0; i < n; ++i) {
while (power2*A[i] < B[i]) {
power2 *= 2;
n_mult2++;
}
}
count += n_mult2;
std::cout << "number of squares = " << n_mult2 << " -> " << power2 << "\n";
// For each pair of exponent, determine the number of subtractions,
// with a fixed number of multiplication by 2
for (int i = 0; i < n; ++i) {
count += n_sub (A[i], B[i], n_mult2, power2);
}
return count;
}
int main() {
int N, M;
std::cin >> N >> M;
auto ans = n_operations (N, M);
std::cout << ans << "\n";
return 0;
}

Find the maximum number of pieces a rod can be cut

Here is the complete problem statement:
Given a rope of length n, you need to find the maximum number of pieces
you can make such that the length of every piece is in set {a, b, c} for
the given three values a, b, c
I know that the optimal solution can be achieved through Dynamic Programming, however, I have not learned that topic yet and I need to solve this problem recursively. With recursion, the main thing is to identify a subproblem and that's what I'm mainly having difficulty with doing. Can anyone give me an intuitive way to think of this problem? Sort of like a higher level description of the recursion if that makes sense. Is there an easier problem similar to this that I can try first that would help me solve this?
Thanks in advance.
It's already quite simple, with recursion we can just check all posibilities, in one step we can either cut away a piece of length a, b, or c so from problem of size n we get sup-problem of smaller size n-x
Of course we need a base case, so when n=0 we have succeeded so we can return 0, in case of n < 0 we have failed so we can return some negative infinity constant
Sample pseudo-code:
int solve(int n){
if(n < 0) return -123456789; //-Infinity
if(n == 0) return 0;
return 1 + max(solve(n-a), solve(n-b), solve(n-c));
}
going to dynamic programming is as simple as setting up memo lookup table
int solve(int n){
if(n < 0) return -123456789; //-Infinity
if(n == 0) return 0;
if(n in memo)return memo[n]
return memo[n] = 1 + max(solve(n-a), solve(n-b), solve(n-c));
}
int maxcut(int n, int a,int b,int c)
{
if(n==0) return 0;
if(n<0) return 1;
int result = max( maxcut(n-a,a,b,c), maxcut(n-b,a,b,c), maxcur(n-c,a,b,c));
if(res == -1) return -1;
return(result+1)
}
The way we should tackle the recursion problem is:
Finding the recursion case (Finding the subproblems)
Finding the base case (The last subproblem case we cannot break in subproblems)
Specific to this problem :
Recursion case: Cutting rope we all the possible values till we cannot break it further smaller subproblem.
Base case: a. It can be completely cut. (valid try)
b.It can't be completely cut. (invalid try)
int maxcut(int n, int a,int b,int c)
{
if(n==0) return 0; //base case a.
if(n<0) return -1; //base case b.
int result = max( maxcut(n-a,a,b,c), maxcut(n-b,a,b,c), maxcur(n-c,a,b,c)); //subproblems for all the cases
if(res == -1) return -1; // boundry coundtion
return(result+1); //to count the valid conditions and return to parent
}
here is the complete code for your problem
#include <iostream>
using namespace std;
int max(int a, int b, int c)
{
if (a > b)
{
if (a > c)
{
return a;
}
else
{
return c;
}
}
else
{
if (b > c)
{
return b;
}
else
{
return c;
}
}
}
int maxpiece(int l, int a, int b, int c)
{
int r;
if (l == 0)
{
return 0;
}
if (l<0)
{
return -1;
}
r = max(maxpiece(l-a, a, b, c), maxpiece(l-b, a, b, c), maxpiece(l-c, a, b, c));
if (r == -1)
return -1;
return r + 1;
}
int main()
{
int lenth;
cout << "enter rope lenth ";
cin >> lenth;
int p1, p2, p3;
cout << endl
<< "enter the only three parameters in which rope can be cut ";
cin >> p1 >> p2 >> p3;
cout << endl
<<"ans = "<< maxpiece(lenth, p1, p2, p3);
}
int cutRope(int n, int a, int b, int c){
// Base cases
if(n == 0) return 0;
if(n < 0) return -1;
int res = max(max(cutRope(n - a, a, b, c), cutRope(n - b, a, b, c)), cutRope(n - c, a, b, c));
if(res == -1) return -1;
return res + 1;
}
int main() {
cout << cutRope(23, 11, 9, 12) << endl;
return 0;
}

How to all possible ways in which any combination of n elements m times can be added to give a result

This is kind of an extension to this question:
Finding all possible combinations of numbers to reach a given sum
The difference is that in the above-linked question, each number(from the set of options) would be counted one time. But what if each number is allowed to be chosen multiple times? For example, if the given set of options is {1, 4, 9}, to get a total of 15, we can do any of the following:
a) 1*15
b) 4*3 + 1*2
c) 4*2 + 1*7
d) 4*1 + 1*11
e) 9*1 + 4*1 + 1*2
f) 9*1 + 1*6
Since you have asked all the possible combinations and not the best one so simple recursion can be used to obtain the results. The main idea is to:
1. Sort the array(non-decreasing).
2. First remove all the duplicates from array.
3. Then use recursion and backtracking to solve
A c++ solution for your problem:
#include <bits/stdc++.h>
using namespace std;
void getNumbers(vector<int>& ar, int sum, vector<vector<int> >& res,vector<int>& r, int i) {
if (sum < 0)
return;
if (sum == 0)
{
res.push_back(r);
return;
}
while (i < ar.size() && sum - ar[i] >= 0)
{
r.push_back(ar[i]);
getNumbers(ar, sum - ar[i], res, r, i);
i++;
r.pop_back();
}
}
vector<vector<int> > getSum(vector<int>& ar, int sum)
{
sort(ar.begin(), ar.end());
ar.erase(unique(ar.begin(), ar.end()), ar.end());
vector<int> r;
vector<vector<int> > res;
getNumbers(ar, sum, res, r, 0);
return res;
}
int main()
{
vector<int> ar;
ar.push_back(1);
ar.push_back(4);
ar.push_back(9);
int n = ar.size();
int sum = 15;
vector<vector<int> > res = getSum(ar, sum);
if (res.size() == 0)
{
cout << "Emptyn";
return 0;
}
for (int i = 0; i < res.size(); i++)
{
if (res[i].size() > 0)
{
cout << " ( ";
for (int j = 0; j < res[i].size(); j++)
cout << res[i][j] << " ";
cout << ")";
}
}
}

Power with divide & conquer algorithm

i want to find for calculating X^46, how many multiplication occurs with optimal D&C approach for calculating Power.
I think this is the best optimal code for calculating power with divide & conquer approach.
int power(int x, unsigned int y)
{
int temp;
if( y == 0)
return 1;
temp = power(x, y/2);
if (y%2 == 0)
return temp*temp;
else
return x*temp*temp;
}
in one note wrote for calculating X^46 with optimal Power code in D&C we need 8 multiplication, but in my code there is 10. anyone correct me?
Edit:
the last code is:
int power(int x, unsigned int y)
{
int temp;
if( y == 0)
return 1;
if( y ==1)
return x;
temp = power(x, y/2);
if (y%2 == 0)
return temp*temp;
else
return x*temp*temp;
}
You left out the optimizing base case of
if (y==1)
return x
and instead require extra multiplications from
temp = power(x, 0)
return x * temp * temp
The extra pair of multiplications come from the unnecessary final recursive call.
You have redundant multiplies due to not earlying out when y==1.
When y==1, you execute the last line:
return x*temp*temp;
which simplifies to:
return x*1*1;
Adding a special case for y==1 will get rid of the additional 2 multiplies.
int power(int x, unsigned int y)
{
int temp;
if( y ==1)
return x;
if (y%2 == 0){
temp = power(x, y/2);
return temp*temp;
}
else{
temp = power(x, (y-1)/2);
return x*temp*temp;
}
}
Best way to do it using the divide and conquer strategy. it will take O(log N) time to complete the execution. It will work for negative exponential also.
I'm doing this in C++:
#include <iostream>
using namespace std;
float power(int a, int b)
{
if (b == 0)
{
return 1;
}
else
{
float temp = power(a, b / 2);
if (b > 0)
{
if (b % 2 == 0)
{
return temp * temp;
}
else
{
return a * temp * temp;
}
}
else
{
return 1/power(a,-b);
}
}
}
int main()
{ int a , b ;
cout<<"Enter a Number:";cin>>a; cout<<"Enter its exponential:";cin>>b;
cout << power(a, b);
}
Output:
Output will be as follow

Fast Iterative GCD

I have GCD(n, i) where i=1 is increasing in loop by 1 up to n. Is there any algorithm which calculate all GCD's faster than naive increasing and compute GCD using Euclidean algorithm?
PS I've noticed if n is prime I can assume that number from 1 to n-1 would give 1, because prime number would be co-prime to them. Any ideas for other numbers than prime?
C++ implementation, works in O(n * log log n) (assuming size of integers are O(1)):
#include <cstdio>
#include <cstring>
using namespace std;
void find_gcd(int n, int *gcd) {
// divisor[x] - any prime divisor of x
// or 0 if x == 1 or x is prime
int *divisor = new int[n + 1];
memset(divisor, 0, (n + 1) * sizeof(int));
// This is almost copypaste of sieve of Eratosthenes, but instead of
// just marking number as 'non-prime' we remeber its divisor.
// O(n * log log n)
for (int x = 2; x * x <= n; ++x) {
if (divisor[x] == 0) {
for (int y = x * x; y <= n; y += x) {
divisor[y] = x;
}
}
}
for (int x = 1; x <= n; ++x) {
if (n % x == 0) gcd[x] = x;
else if (divisor[x] == 0) gcd[x] = 1; // x is prime, and does not divide n (previous line)
else {
int a = x / divisor[x], p = divisor[x]; // x == a * p
// gcd(a * p, n) = gcd(a, n) * gcd(p, n / gcd(a, n))
// gcd(p, n / gcd(a, n)) == 1 or p
gcd[x] = gcd[a];
if ((n / gcd[a]) % p == 0) gcd[x] *= p;
}
}
}
int main() {
int n;
scanf("%d", &n);
int *gcd = new int[n + 1];
find_gcd(n, gcd);
for (int x = 1; x <= n; ++x) {
printf("%d:\t%d\n", x, gcd[x]);
}
return 0;
}
SUMMARY
The possible answers for the gcd consist of the factors of n.
You can compute these efficiently as follows.
ALGORITHM
First factorise n into a product of prime factors, i.e. n=p1^n1*p2^n2*..*pk^nk.
Then you can loop over all factors of n and for each factor of n set the contents of the GCD array at that position to the factor.
If you make sure that the factors are done in a sensible order (e.g. sorted) you should find that the array entries that are written multiple times will end up being written with the highest value (which will be the gcd).
CODE
Here is some Python code to do this for the number 1400=2^3*5^2*7:
prime_factors=[2,5,7]
prime_counts=[3,2,1]
N=1
for prime,count in zip(prime_factors,prime_counts):
N *= prime**count
GCD = [0]*(N+1)
GCD[0] = N
def go(i,n):
"""Try all counts for prime[i]"""
if i==len(prime_factors):
for x in xrange(n,N+1,n):
GCD[x]=n
return
n2=n
for c in xrange(prime_counts[i]+1):
go(i+1,n2)
n2*=prime_factors[i]
go(0,1)
print N,GCD
Binary GCD algorithm:
https://en.wikipedia.org/wiki/Binary_GCD_algorithm
is faster than Euclidean algorithm:
https://en.wikipedia.org/wiki/Euclidean_algorithm
I implemented "gcd()" in C for type "__uint128_t" (with gcc on Intel i7 Ubuntu), based on iterative Rust version:
https://en.wikipedia.org/wiki/Binary_GCD_algorithm#Iterative_version_in_Rust
Determining number of trailing 0s was done efficiently with "__builtin_ctzll()". I did benchmark 1 million loops of two biggest 128bit Fibonacci numbers (they result in maximal number of iterations) against gmplib "mpz_gcd()" and saw 10% slowdown. Utilizing the fact that u/v values only decrease, I switched to 64bit special case "_gcd()" when "<=UINT64_max" and now see speedup of 1.31 over gmplib, for details see:
https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=311893&p=1873552#p1873552
inline int ctz(__uint128_t u)
{
unsigned long long h = u;
return (h!=0) ? __builtin_ctzll( h )
: 64 + __builtin_ctzll( u>>64 );
}
unsigned long long _gcd(unsigned long long u, unsigned long long v)
{
for(;;) {
if (u > v) { unsigned long long a=u; u=v; v=a; }
v -= u;
if (v == 0) return u;
v >>= __builtin_ctzll(v);
}
}
__uint128_t gcd(__uint128_t u, __uint128_t v)
{
if (u == 0) { return v; }
else if (v == 0) { return u; }
int i = ctz(u); u >>= i;
int j = ctz(v); v >>= j;
int k = (i < j) ? i : j;
for(;;) {
if (u > v) { __uint128_t a=u; u=v; v=a; }
if (v <= UINT64_MAX) return _gcd(u, v) << k;
v -= u;
if (v == 0) return u << k;
v >>= ctz(v);
}
}

Resources