Time complexity of recursive algorithm with two recursive calls - c++

I am trying to analyze the Time Complexity of a recursive algorithm that solves the Generate all sequences of bits within Hamming distance t problem. The algorithm is this:
// str is the bitstring, i the current length, and changesLeft the
// desired Hamming distance (see linked question for more)
void magic(char* str, int i, int changesLeft) {
if (changesLeft == 0) {
// assume that this is constant
printf("%s\n", str);
return;
}
if (i < 0) return;
// flip current bit
str[i] = str[i] == '0' ? '1' : '0';
magic(str, i-1, changesLeft-1);
// or don't flip it (flip it again to undo)
str[i] = str[i] == '0' ? '1' : '0';
magic(str, i-1, changesLeft);
}
What is the time complexity of this algorithm?
I fond myself pretty rusty when it comes to this and here is my attempt, which I feel is no where near the truth:
t(0) = 1
t(n) = 2t(n - 1) + c
t(n) = t(n - 1) + c
= t(n - 2) + c + c
= ...
= (n - 1) * c + 1
~= O(n)
where n is the length of the bit string.
Related questions: 1, 2.

It's exponential:
t(0) = 1
t(n) = 2 t(n - 1) + c
t(n) = 2 (2 t(n - 2) + c) + c = 4 t (n - 2) + 3 c
= 2 (2 (2 t(n - 3) + c) + c) + c = 8 t (n - 3) + 7 c
= ...
= 2^i t(n-i) + (2^i - 1) c [at any step i]
= ...
= 2^n t(0) + (2^n - 1) c = 2^n + (2^n - 1) c
~= O(2^n)
Or, using WolframAlpha: https://www.wolframalpha.com/input/?i=t(0)%3D1,+t(n)%3D2+t(n-1)+%2B+c
The reason it's exponential is that your recursive calls are reducing the problem size by 1, but you're making two recursive calls. Your recursive calls are forming a binary tree.

Related

ZSum : How to debug a problem in a coding challenge?

To begin this is a question from SPOJ. I was having some doubts about it.
I would like to know, what is the problem with my approach, which used Binary Exponentiation in 2 steps, the bind function is used to remove the overflow for very large values of A and MOD, and below, is the normal Binary Exponentiation function. How could I solve it?
#define MOD 1000000007ll
using ll long long
ll binAdd(ll a,ll b)
{
ll res=0;
while(b)
{
if(b&1)
res = (res+a) %MOD;
a = (a+a) % MOD;
b>>=1;
}
return res;
}
ll binPow(ll a,ll b)
{
a%=MOD;
ll res=1;
while(b)
{
if(b&1)
res = binAdd(res,a);
a = binAdd(a,a);
b>>=1;
}
return res;
}
ll Z(ll n,ll k)
{
ll s=0;
for(int i=1;i<=n;i++)
s+=binPow(i,k);
for(int i=1;i<=n;i++)
s+=binPow(i,i);
return s;
}
void solve(){
ll n,k;
while(cin >> n >> k && (n!=0 || k!=0))
cout << ((Z(n,k) + Z(n-1,k) - 2LL*Z(n-2,k))) << endl;
}
Input :
10 3
9 31
83 17
5 2
0 0
Expected Output:
4835897
2118762
2285275
3694
Actual Output:
1774843373
1919101650
4154173929
3694
Let's start with the problem statement from the page1 linked by the OP (emphasis mine).
For two given integers n and k find (Zn + Zn-1 - 2Zn-2) mod 10000007, where Zn = Sn + Pn and Sn = 1k + 2k + 3k + … + nk and Pn = 11 + 22 + 33 + … + nn.
...
Constraints
1 < n < 200000000
0 < k < 1000000
The posted attempt has some mistakes that prevents it to produce the expected output
#define MOD 1000000007ll has a typo that makes MOD two orders of magnitude bigger than the required modulo, which is 10'000'007.
using ll long long lacks a = and a ; (typoes, maybe) and even if corrected, it may be confusing.
In Z, the loops have the variable i declared as int, but it goes up to n, which is a long long variable.
The output of solve is the result of the formula Z(n,k) + Z(n-1,k) - 2LL*Z(n-2,k), but that value (all the operations, actually) should be taken modulo MOD.
Once fixed, the algorithm yields the expected results2, but it's still quite inefficient.
The (IMHO wrongly named) function binAdd(a, b) returns the result of (a * b) % MOD without performing a direct multiplication between a and b. This avoids overflowing (and UB) when a > std::numeric_limits<long long>::max() / b (but it still requires std::max(a, res) <= std::numeric_limits<long long>::max() - a at every step).
Given the value of MOD (and the upper limit of n), a 64-bit integer type is wide enough to perform all the needed modular multiplication using the known formula (A * B) mod C = (A mod C * B mod C) mod C without overflowing.
Note that this is also the reason why the loops in OP's Z function can accumulate all those sums without overflowing.
There's no need to loop linearly up to n:
Zn + Zn-1 - 2Zn-2 = Sn + Sn-1 - 2Sn-2 + Pn + Pn-1 - 2Pn-2
= 1k + 2k + 3k + … + (n - 2)k + (n - 1)k + nk
+ 1k + 2k + 3k + … + (n - 2)k + (n - 1)k
- (1k + 2k + 3k + … + (n - 2)k) * 2
+ 11 + 22 + 33 + … + (n - 2)n-2 + (n - 1)n-1 + nn
+ 11 + 22 + 33 + … + (n - 2)n-2 + (n - 1)n-1
- (11 + 22 + 33 + … + (n - 2)n-2) * 2 =
= 2((n - 1)k + (n - 1)n-1) + nk + nn
This leads to an O(log(max(n,k)) algorithm3.
1) https://www.spoj.com/problems/ZSUM/
2) https://godbolt.org/z/8sbo7Whxd
3) https://godbolt.org/z/bnsz94cf5

modulo formula in C++

I Have this formula:
(n - 1)! ((n (n - 1))/2 + ((n - 1) (n - 2))/4)
2<=n<=100000
I would like to modulate the result of this from this formula by any modulo, but for the moment let's assume that it is constant, MOD = 999999997. Unfortunately I can't just calculate the result and modulate it, because unfortunately I don't have variables larger than 2^64 at my disposal, so the main question is. What factors to modulate by MOD to get the results%MOD ?
Now let's assume that n=19. What is in brackets is equal to 247.5
18! = 6402373705728000.
(6402373705728000 * 247.5)mod999999997 = 921442488.
Unfortunately, in case I modulate 18! first, the result will be wrong, because (18!)mod999999997 = 724935119. (724935119 * 247.5)mod9999997 = 421442490.
How to solve this problem?
I think the sum could be break down. The only tricky part here is that (n - 1)(n - 2)/4 may have a .5 decimal., as n(n-1) / 2 will always be integer.
S = (n - 1)! * ((n (n - 1))/2 + ((n - 1) (n - 2))/4)
= [(n-1)! * (n*(n-1)/2)] + [(n-1)! * (n-1)(n-2)/4]
= A + B
A is easy to do. With B, if (n-1)(n-2) % 4 == 0 then there's nothing else either, else you can simplified to X/2, as (n-1)(n-2) is also divisible by 2.
If n = 2, it's trivial, else if n > 2 there's always a 2 in the representation of (N-1)! = 1x2x3x ... xN. In that case, simply calculate ((N-1)!/2) = 1x3x4x5x ... xN.
Late example:
N = 19
MOD = 999999997
--> 18! % MOD = 724935119 (1)
(18!/2) % MOD = 862467558 (2)
n(n-1)/2 = 171 (3)
(n-1)(n-2)/2 = 153 (4)
--> S = (1)*(3) + (2)*(4) = 255921441723
S % MOD = 921442488
On another note, if mod is some prime number, like 1e9+7, you can just apply Fermat's little theorem to calculate multiplicative inverse as such:
(a/b) % P = [(a%P) * ((b^(P-2)) % P)] % P (with P as prime, a and b are co-prime to P)
You will have to use 2 mathematical formulas here:
(a + b) mod c == (a mod c + b mod c) mod c
and
(a * b) mod c == (a mod c * b mod c) mod c
But those are only valid for integers. The nice part here is that formula can only be integer for n >= 2, provided you compute it as:
(((n - 1)! * n * (n - 1))/2) + (((n - 1)! * (n - 1) * (n - 2))/4)
1st part is integer | 2nd part is too
for n == 2, first part boils down to 1 and second is 0
for n > 2 either n or n-1 is even so first part is integer, and again eithe n-1 of n-2 is even and (n-1)! is also even so second part is integer. As your formula can be rewritten to only use additions and multiplications it can be computed.
Here is a possible C++ code (before unsigned long long is required):
#include <iostream>
template<class T>
class Modop {
T mod;
public:
Modop(T mod) : mod(mod) {}
T add(T a, T b) {
return ((a % mod) + (b % mod)) % mod;
}
T mul(T a, T b) {
return ((a % mod) * (b % mod)) % mod;
}
int fact_2(T n) {
T cr = 1;
for (T i = 3; i <= n; ++i) {
cr = mul(cr, i);
}
return cr;
}
};
template<class T>
T formula(T n, T mod) {
Modop<T> op = mod;
if (n == 2) {
return 1;
}
T second, first = op.mul(op.fact_2(n - 1), op.mul(n, n - 1));
if (n % 2 == 0) {
second = op.mul(op.fact_2(n - 1), op.mul((n - 2)/ 2, n - 1));
}
else {
second = op.mul(op.fact_2(n - 1), op.mul(n- 2, (n - 1) / 2));
}
return op.add(first, second);
}
int main() {
std::cout << formula(19ull, 999999997ull) << std::endl;
return 0;
}
First of All , for n=2 we can say that the result is 1.
Then, the expression is equal to: (n*(n-1)(n-1)!)/2 + (((n-1)(n-2)/2)^2)*(n-3)! .
lemma: For every two consecutive integer number , one of them is even.
By lemma we can understand that n*(n-1) is even and also (n-1)*(n-2) is even too. So we know that the answer is an integer number.
First we calculate (n*(n-1)(n-1)!)/2 modulo MOD. We can calculate (n(n-1))/2 that can be saved in a long long variable like x, and we get the mod of it modulo MOD:
x = (n*(n-1))/2;
x %= MOD;
After that for: i (n-1 -> 1) we do:
x = (x*i)%MOD;
And we know that both of 'x' and 'i' are less than MOD and the result of
multiplication can be save in a long long variable.
And likewise we do the same for (((n-1)(n-2)/2)^2)(n-3)! .
We calculate (n-1)*(n-2)/2 that can be save in a long long variable like y, and we get the mod of it modulo MOD:
y = ((n-1)*(n-2))/2;
y %= MOD;
And after that we replace (y^2)%MOD on y because we know that y is less than MOD and y*y can be save in a long long variable:
y = (y*y)%MOD;
Then like before for: i (n-3 -> 1) we do:
y = (y*i)%MOD;
And finally the answer is (x+y)%MOD

Calculating the summation of powers of a number modulo a number

There are 3 numbers: T, N, M. 1 ≤ T, M ≤ 10^9, 1 ≤ N ≤ 10^18 .
What is asked in the problem is to compute [Σ(T^i)]mod(m) where i varies from 0 to n. Obviously, O(N) or O(M) solutions wouldn't work because of 1 second time limit. How should I proceed?
As pointed out in previous answers, you may use the formula for geometric progression sum. However there is a small problem - if m is not prime, computing (T^n - 1) / (T - 1) can not be done directly - the division will not be a well-defined operations. In fact there is a solution that can handle even non prime modules and will have a complexity O(log(n) * log(n)). The approach is similar to binary exponentiation. Here is my code written in c++ for this(note that my solution uses binary exponentiation internally):
typedef long long ll;
ll binary_exponent(ll x, ll y, ll mod) {
ll res = 1;
ll p = x;
while (y) {
if (y % 2) {
res = (res * p) % mod;
}
p = (p * p) % mod;
y /= 2;
}
return res;
}
ll gp_sum(ll a, int n, ll mod) {
ll A = 1;
int num = 0;
ll res = 0;
ll degree = 1;
while (n) {
if (n & (1 << num)) {
n &= (~(1 << num));
res = (res + (A * binary_exponent(a, n, mod)) % mod) % mod;
}
A = (A + (A * binary_exponent(a, degree, mod)) % mod) % mod;
degree *= 2;
num++;
}
return res;
}
In this solution A stores consecutively the values 1, 1 + a, 1 + a + a^2 + a^3, ...1 + a + a^2 + ... a ^ (2^n - 1).
Also just like in binary exponentiation if I want to compute the sum of n degrees of a, I split n to sum of powers of two(essentially using the binary representation of n). Now having the above sequence of values for A, I choose the appropriate lengths(the ones that correspond to 1 bits of the binary representation of n) and multiply the sum by some value of a accumulating the result in res. Computing the values of A will take O(log(n)) time and for each value I may have to compute a degree of a which will result in another O(log(n)) - thus overall we have O(log(n) * log (n)).
Let's take an example - we want to compute 1 + a + a^2 .... + a ^ 10. In this case, we call gp_sum(a, 11, mod).
On the first iteration n & (1 << 0) is not zero as the first bit of 11(1011(2)) is 1. Thus I turn off this bit setting n to 10 and I accumulate in res: 0 + 1 * (a ^ (10)) = a^10. A is now a + 1.
The next second bit is also set in 10(1010(2)), so now n becomes 8 and res is a^10 + (a + 1)*(a^8)=a^10 + a^9 + a^8. A is now 1 + a + a^2 + a^3
Next bit is 0, thus res stays the same, but A will become 1 + a + a^2 + ... a^7.
On the last iteration the bit is 1 so we have:
res = a^10 + a^9 + a^8 + a^0 *(1 + a + a^2 + ... +a^7) = 1 + a .... + a ^10.
One can use an algorithm which is similar to binary exponentiation:
// Returns a pair <t^n mod m, sum of t^0..t^n mod m>,
// I assume that int is big enough to hold all values without overflowing.
pair<int, int> calc(int t, int n, int m)
if n == 0 // Base case. t^0 is always 1.
return (1 % m, 1 % m)
if n % 2 == 1
// We just compute the result for n - 1 and then add t^n.
(prevPow, prevSum) = calc(t, n - 1, m)
curPow = prevPow * t % m
curSum = (prevSum + curPow) % m
return (curPow, curSum)
// If n is even, we compute the sum for the first half.
(halfPow, halfSum) = calc(t, n / 2, m)
curPow = halfPow * halfPow % m // t^n = (t^(n/2))^2
curSum = (halfSum * halfPow + halfSum) % m
return (curPow, curSum)
The time complexity is O(log n)(the analysis is the same as for the binary exponentiation algorithm). Why is it better than a closed form formula for geometric progression? The latter involves division by (t - 1). But it is not guaranteed that there is an inverse of t - 1 mod m.
you can use this:
a^1 + a^2 + ... + a^n = a(1-a^n) / (1-a)
so, you just need to calc:
a * (1 - a^n) / (1 - a) mod M
and you can find O(logN) way to calc a^n mod M
It's a geometric series whose sum is equal to :

Complexity of a recursive algorithm

I have a recursive algorithm like :
int alg(int n) {
if (n == 0)
return 2;
for (int i = 0; i<= n-1; ++i)
alg(i);
}
Obviously the n == 0 case is Θ(1). However I am having trouble understanding how it really works. I mean it must be something like :
T(n) = T(0) + T(1) + ... + T(n-1).
And then we have to give T(1), T(2), .., T(n-1) = xT(0). I can understand the way it goes for n=0 and n=1, but for bigger n it goes wrong.
You can observe that:
T(n) = T(0) + T(1) + ... + T(n-2) + T(n-1)
T(n - 1) = T(0) + T(1) + ... + T(n-2)
Therefore
T(n) = 2 * T(n-1)
At this point, we can conclude that the complexity is O(2n). Actually, it is Θ(2n).

alternative to if statement in c++

i am working on an algorithm and want to make my code more efficient.my code uses simple arithmetic and comparison statements.however,i want to replace if statements,as they could be time consuming.this code would be run over a million times,so even the slightest improvement is appreciated.please answer!here is the code-
int_1024 sqcalc(int_1024 s,int_1024 f){
f=f*20;
s=s-81;
s=s-(f*9);
if(s>=0){
return 9;
}
s=s+f;
s=s+17;
if(s>=0){
return 8;
}
s=s+f;
s=s+15;
if(s>=0){
return 7;
}
s=s+f;
s=s+13;
if(s>=0){
return 6;
}
s=s+f;
s=s+11;
if(s>=0){
return 5;
}
s=s+f;
s=s+9;
if(s>=0){
return 4;
}
s=s+f;
s=s+7;
if(s>=0){
return 3;
}
s=s+f;
s=s+5;
if(s>=0){
return 2;
}
s=s+f;
s=s+3;
if(s>=0){
return 1;
}
s=s+f;
s=s+1;
if(s>=0){
return 0;
}
}
i wish to replace if checks,since i 'think' they make the algorithm slow.any suggestions?int_1024 is a ttmath variable with 1000's of bits,so saving on it might be a good option?division or multiplication for such a large number might be slow,so i tried using addition,but to no avail.help please.
I don't know if it is any faster, but it is considerably shorter (and easier to analyze).
int k[] = { 17, 15, 13, 11, 9, 7, 5, 3, 1 };
int r = 0;
f *= 20;
s -= 81;
s -= f * 9;
while (s < 0) {
s += f;
s += k[r];
if (++r == 9) break;
}
if (s >= 0) return 9-r;
Edit:
In fact, the original poster came up with a clever way to optimize this loop by pre-computing the sum of constants in the k array, and compared s against the sums, rather than incrementally adding them to s.
Edit:
I followed moonshadow's analysis technique, but arrived at a different equation. Original TeX formatting replaced with ASCII art (I tried to get MathJax to render the TeX for me, but it wasn't working):
S[0] = s >= 0 => 9 - 0
S[1] = S[0] + f + 19 - 2*1 >= 0 => 9 - 1
S[2] = S[1] + f + 19 - 2*2 >= 0 => 9 - 2
...
S[i] = S[i-1] + f + 19 - 2*i >= 0 => 9 - i
So to calculate S[n]:
S[n] = S[n-1] + f + 19 - 2n
.-- n
=> S[n] = s + > (f + 19 - 2*i)
`-- i=1 .-- n
=> S[n] = s + n(f + 19) - 2 > i
`-- i=1
=> S[n] = s + n(f + 19) - n(n+1)
2
=> S[n] = s + n(f + 18) - n
So, the inequality S[n] >= 0 is a quadratic equation in n. Assuming s < 0, we want n to be the ceiling of the solution to the quadratic.
+-- --+
| _____________ |
| / 2 |
| f + 18 - . / (f + 18) + 4s |
| ` |
n = | --------------------------- |
| 2 |
So the routine would look something like:
f *= 180;
s -= 81;
s -= f;
if (s >= 0) return 9;
f /= 9;
f += 18;
s *= 4;
int1024_t ff = f;
ff *= f;
ff += s;
ff = ff.Sqrt();
f -= ff;
f += f.Mod2();
return 9 - f/2;
However, I am not sure the expense of performing these operations on your big integer objects is worth implementing to replace the simple loop shown above. (Unless you expect to extend the function and would require a much longer loop.)
To be faster than the loop, the big integer square root implementation would have to always converge within 4 iterations to beat the average expected 4.5 iterations of the existing while loop. However the ttmath implementation does not seem to be calculating an integer square root. It seems to calculate a floating point square root and then rounding the result, which I would guess would be much slower than the loop.
First of all, I note that if the condition of the final if() is false, the return value is undefined. You probably want to fix that.
Now, the function starts with
f=f*20;
s=s-81;
s=s-(f*9);
if(s>=0){
return 9;
}
and the rest looks incredibly repetitive. Let's see if we can use that repetition. Let's build a table of inequalities - values of s vs the eventual result:
s + (f+17) >= 0: 8
s + (f+17) + (f+15) >= 0: 7
s + (f+17) + (f+15) + (f+13) >= 0: 6
.
.
s + (f+17) + (f+15) + (f+13) + ... + (f+1) >= 0: 0
So, each line tests to see if s + some multiple of f + some constant is greater than 0. The value returned, the constant and the multiple of f all look related. Let's try expressing the relationship:
(s + ((9-n)*f) + (2*n)-1 >= 0)
Let's rearrange that so n is on one side.
(s + (9*f) - (n*f) + (2*n)-1 >= 0)
(s + (9*f) +1 >= (n*f) - (2*n))
(s + (9*f) +1 >= n*(f - 2))
n <= ((s + (9*f) +1) / (f - 2)
Now, the function has a range of return values for different inputs. In fact, we are interested in values of n in the range 0..8: the function supplied is undefined for inputs that would yield n < 0 (see above). The preamble ensures we never see inputs that would yield n > 8.
So we can just say
int_1024 sqcalc(int_1024 s,int_1024 f){
f=f*20;
s=s-81;
s=s-(f*9);
if(s>=0){
return 9;
}
return (s + (9*f) +1) / (f - 2);
}
and for all cases where the result is not undefined, the behaviour should be the same as the old version, without needing tons of conditionals or a loop.
Demonstration of accuracy is at http://ideone.com/UzMZs.
According to the OP's comment, the function is trying to find all values that satisfy the inequality:
N * ((20 * F) + N) <= S
For all N, given an F and S.
Using algebra, this comes out to:
1) N^2 + 20Fn - S <= 0 (where N^2 is N*N or sqr(N))
The OP should use some constants for F and N and solve algebraically (sp?) or search the web for "C++ find root quadratic equation".
One a function is selected, then profile the function and optimize if necessary.
i tried solving the quadratics,and it makes the function slower for larger digits.following the answer by #user315052,i made this code.
int_1024 sqcalc(int_1024 s,int_1024 f){
int k[] = { 0, 17, 32, 45, 56, 65, 72, 77, 80, 81 };
f=f*20;
s=((f*9)+81)-s;
int i=0;
while(s>k[i]){
s-=f;
i++;
}
return 9-i;
}
in this code,instead of subtracting a number and then comparing with zero,i directly compare it with the number.by far,this produces the fastest results.i could do binary search though....