问题描述:
计算ackerman函数值:
Ack(m,n)
if(m==0) n+1;
if(n==0) ack(m-1,1)
if(m&&n>0) ack((m-1),ack(m,n-1))
输入格式:
从文件ackerman.in读入数据,第一行为两个数,即M和N,其中0<=M<=3,0<=N<=11。
输出格式:
向文件ackerman.out输出ack(m,n)的值。
样例1:
ackerman.in |
ackerman.out |
0 1 |
2 |
说明:有极限数据,用朴素递归算法只得36分
提示:ackerman函数的增长是很惊人的,在我们想象得到的函数值中,m远小于10
用f[I,j]保存函数值时,j可能很大。
在分析并查集的算法复杂度时曾提到:采用路径压缩后,每一次查询所用的时间复杂度为增长极为缓慢的ackerman函数的反函数——α(x)。对于可以想象到的n,α(n)都是在5之内的。
#include<cstdio> using namespace std; int a[10000][10000]; int ack(int m,int n){ if(a[m][n]!=0){ return a[m][n]; } if(m==0){ return a[m][n]=n+1; } if(n==0){ return a[m-1][1]=ack(m-1,1); } if(m>0&&n>0){ return ack((m-1),ack(m,n-1)); } } int main(){ freopen("ackerman.in","r",stdin); freopen("ackerman.out","w",stdout); int m,n; while(scanf("%d%d",&m,&n)){ printf("%d\n",ack(m,n)); } }