The Ackermann function is a computable function which grows very, very quickly as its inputs grow. For example, while
A
(
1
,
2
)
,
A
(
2
,
2
)
,
and
A
(
3
,
2
)
are equal to
4
,
7
,
and
2
9
,
respectively,
A
(
4
,
2
)
≈
2
×
1
0
1
9
7
2
8
.
The Ackermann function can be defined as follows: A ( m , n ) = ⎩ ⎪ ⎨ ⎪ ⎧ n + 1 A ( m − 1 , 1 ) A ( m − 1 , A ( m , n − 1 ) ) if m = 0 if m > 0 and n = 0 if m > 0 and n > 0 .
What are the last 3 digits of A ( 4 , 5 ) ?
This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try
refreshing the page, (b) enabling javascript if it is disabled on your browser and,
finally, (c)
loading the
non-javascript version of this page
. We're sorry about the hassle.
Well this would have helped... I wrote a simple function with 3 if statements and it took about 5 minutes to run.
Its mainly because the function doesn't have to deal with the Ackermann function's ridiculously large numbers..
Because m is rather small, we can use the table given here
A ( 4 , 5 ) = eight 2’s 2 2 2 2 2 2 2 2 − 3
We consider the last three digits of ( A ( 4 , 5 ) + 3 ) , that is modulo 1 0 0 0
1 0 0 0 = 8 × 1 2 5 , with 8 and 1 2 5 coprime positive integers, we will use Chinese Remainder Theorem
Denote B = ( A ( 4 , 5 ) + 3 ) , because B has plenty of powers of 2 's, so B m o d 8 = 0
With gcd ( 2 , 1 2 5 ) = 1 , Euler Totient Function is applicable, ϕ ( 1 2 5 ) = ϕ ( 5 3 ) = 1 2 5 ( 1 − 5 1 ) = 1 0 0
B m o d 1 2 5 = 2 2 2 2 2 2 2 2 m o d 1 0 0 m o d 1 2 5
Repeat: 1 0 0 = 4 × 2 5 , with gcd ( 4 , 2 5 ) = 1 , and gcd ( 2 , 2 5 ) = 1 , ϕ ( 2 5 ) = ϕ ( 5 2 ) = 2 5 ( 1 − 5 1 ) = 2 0
Denote C = seven 2’s 2 2 2 2 2 2 2
C m o d 4 = 0
C m o d 2 5 = 2 2 2 2 2 2 2 m o d 2 0 m o d 2 5
Repeat again: 2 0 = 4 × 5 , gcd ( 4 , 5 ) = 1 , and gcd ( 2 , 5 ) = 1 , ϕ ( 5 ) = ϕ ( 5 1 ) = 5 ( 1 − 5 1 ) = 4
Denote D = six 2’s 2 2 2 2 2 2 ,
D m o d 4 = 0 , and by Fermat's Little Theorem
D m o d 5 = 2 2 2 2 2 2 m o d 4 m o d 5 = 1
D satisfy the linear congruences:
x 1 ≡ 0 ( m o d 4 )
x 1 ≡ 1 ( m o d 5 )
By Chinese Remainder Theorem D m o d 2 0 = 1 6 , consider modulo 2 5
Then C ≡ 2 1 6 ≡ ( 2 4 ) 4 ≡ ( 1 6 ) 4 ≡ ( − 9 ) 4 ≡ 1 1
Again, C satisfy the linear congruences:
x 2 x 2 ≡ ≡ 0 ( m o d 4 ) 1 1 ( m o d 2 5 )
By Chinese Remainder Theorem C m o d 1 0 0 = 3 6
So by considering modulo 1 2 5
B ≡ 2 3 6 ≡ ( 2 7 ) 5 ⋅ 2 ≡ 3 5 ⋅ 2 ≡ − 7 ⋅ 2 ≡ − 1 4 ≡ 1 1 1
One last time, B satisfy the linear congruences:
x 3 x 3 ≡ ≡ 0 ( m o d 8 ) 1 1 1 ( m o d 1 2 5 )
By Chinese Remainder Theorem B m o d 1 0 0 0 = 7 3 6
Hence,
( A ( 4 , 5 ) + 3 ) m o d 1 0 0 0 A ( 4 , 5 ) m o d 1 0 0 0 = = 7 3 6 7 3 3
Note: Using the same logic, the last three digits of A ( 4 , n ) is 7 3 3 for n = 2 , 3 , 4 , …
r u human ?!!! ;)
The solution to this is quite simple... Looking at the function one can certainly say that its a question pertaining to a recursive function algorithm. But the answer A(4,5) is so large that it overflows the memory even for a long long int (in C++). But since the question only talks about finding the 3 digits only, just a little tweak of adding a mod 1000 for n+1 will work it out.. :D
So here's the code (in C++)
#include <iostream>
#include <conio.h>
using namespace std;
int x = 4, y = 2;
long long int A(int m, int n) {
if( m == 0 )
return (n+1)%1000;
else if( m > 0 && n == 0 )
return A(m-1, 1);
else if( m > 0 && n > 0 )
return A( m-1, A(m,n-1) );
}
int main() {
cout << A(4,5);
getch();
}
I wrote exactly same code but didn't work. (The IDE just closed without even showing any error) . I think you did this on a super computer because A(4,5) would still be calculated and then last 3 digits would be printed. Kindly help if i am wrong.
I used DP memoization for this, combined with the fact that you only need the last 3 digits.. Ran in seconds. Programming language was in JavaScript.
var A=[[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]];
function a(m,n){
if(A[m][n])return A[m][n];
if(!m) return A[m][n] = n+1;
if(n==0 && m>0) return A[m][n] = a(m-1,1)%1000;
if(m>0 && n>0) return A[m][n] = a(m-1,a(m,n-1))%1000;
}
Let tower(n) denote a tower of n 2s. Some easy inductions give A(4,n) = tower(n+3) - 3.
Obviously tower(5) = 0 mod 8. But 2 8 = 1 6 = 2 1 6 mod 20, so 2 8 n = 1 6 mod 20 for any n and hence tower(6) = 16 mod 20.
Similarly, 2 1 6 = 3 6 = 2 1 6 + 2 0 mod 100, hence tower(7) = 36 mod 100.
Finally, 2 3 6 = 7 3 6 = 2 1 3 6 mod 1000, so tower(8) = 736 mod 1000 and hence A(4,5) has last three digits 733.
Since we are required to print last three digits only we should pass last 3 digits only in every recursive call. The following JAVA code illustrates my idea.
public class Ackerman {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(new Ackerman().A(4, 5));
}
int A(int m, int n) {
if (m == 0)
return n + 1;
else if (m > 0 && n == 0)
return A((m - 1) % 1000, 1); // n%1000 will give last three digits
else
return A((m - 1) % 1000, A(m % 1000, (n - 1) % 1000));
}
}
Why doesn't this work in c++? (The IDE just closed without even showing any error) .
there must be some problem with your code. Try to find some thing u may have missed.
Here's my code :-
#include<iostream.h>
#include<conio.h>
double A(double m,double n);
void main()
{
double a, b, c;
cin>>a>>b;
c=A(a,b);
cout<<"Answer "<<c;
getch();
}
double A(double m,double n)
{
if (m==0)
return (n+1);
else if ((m>0) && (n==0))
return (A((m-1)%1000,1));
else if ((m>0) && (n>0))
{
double d=A(m%1000,(n-1)%1000);
return (A(((m-1)%1000),d));
}
else cout<<"Oooops!!";
}
@Aakarshit Uppal – my code gave the correct output on a laptop ... no super computer is needed for this question if your algorithm is correct . As i told you already there were many problems with your C++ code. I'm mentioning some of them: ->> % operator should be used with integers not with floating point numbers(double in your case). ->> using namespace std was missing the above two problems will result in compilation error. I don't know how you did not get one.
Anyways i have corrected your code . Do have a look at it, Provide the inputs from console(4 5) and keep calm for 5-10 secs you will get the output for sure(After all its not a supercomputer right?? :D ). Hope its clear. Code:- // replace hash with # symbol. I did it because of formatting issues
hash include <iostream>
hash include <conio.h>
using namespace std;
int A(int m, int n);
void main() {
int a, b, c;
cin >> a >> b;
c = A(a, b);
cout << "Answer " << c;
}
int A(int m, int n) { if (m == 0) return (n + 1);
else if ((m > 0) && (n == 0))
return (A((m - 1) % 1000, 1));
else if ((m > 0) && (n > 0))
return A((m - 1) % 1000, A(m % 1000, (n - 1) % 1000));
else
cout << "Oooops!!";
}
Problem Loading...
Note Loading...
Set Loading...
It is possible to prove the following properties of A ( m , n ) for m < 3
A ( 0 , n ) = n + 1
A ( 1 , n ) = n + 2
A ( 2 , n ) = 2 n + 3
A ( 3 , n ) = 2 n + 3 − 3
Since A ( 4 , 5 ) is large computing the whole integer would take a while. But since all we need are the last three digits we can just find A ( m , n ) m o d 1 0 0 0 at every recursive call..Ran in 0.001 seconds on my machine.