ZOJ 2595 Ackerman's Function

来源:互联网 发布:网络十大神曲 编辑:程序博客网 时间:2024/05/21 06:46

ZOJ2595 Ackerman’s Function

downloadsource code (ZOJ2595.cpp) [recursion, number theory, Euler's theorem]

求Ackerman函数A(n, m)模t的值。

n\m12345
1246810… (2m) 2 \times m …22481632… (2m2 \uparrow m  …32416222222222… (m2) 2 \uparrow\uparrow m …42465536\begin{matrix}\underbrace{2^{2^{\cdot^{\cdot^{\cdot^2}}}}} \\ 65536 \end{matrix}overflow.. 2 \uparrow\uparrow\uparrow m …524overflow.. 2 \uparrow\uparrow\uparrow\uparrow m ..

上表中用到了Knuth’s up-arrow notation。从上面的表中可以看出n=1, n=2, m=1, m=2的时候问题都很简单,而事实

上n和m只要稍稍大一点,这个数就大得不得了,而它关于t的余数就是定值。证明就是利用欧拉定理

欧拉定理的内容是:如果a和n互质,那么aφ(n)=1(mod n);对于任意a, n和较大的b,有ab=aφ(n)+b mod φ(n)(mod n)。

于是利用欧拉定理,问题就很简单了,我们把上面问题的极限记为x=gao(a, b)。那么假设y=gao(a, φ(b)),就有

x=aφ(b)+ymod b,而如果b=1,显然x=0。

对于n=3&&m<32和n==4&&m==3的时候,结果未必收敛到了上面的极限,所以也要特殊处理,方法

类似求那个极限的递归。

Ackerman's Function

Time Limit: 10 Seconds      Memory Limit: 32768 KB

Ackerman's function is well known to all specialists in the theory of computation. It is the function in two positive integer arguments defined as follows:

It is not primitive recursive, more of that, A(i, i) grows faster than any primitive recursive function. In this problem your task is to calculate

A(n,m) mod t

for given t and several n and m. Here "x mod y" means the remainder of integer division of x by y - such r that 0 <= r < y and there exists integer q, such that x = qy + r.


Input

The input contains multiple test cases. The first line of the input is a single integer T (1 <= T <= 20) which is the number of test cases. T test cases follow, each preceded by a single blank line.

The first line of each test case contains t (1 <= t <= 100) and then several lines follow. Each of them contains two integers - n and m (1 <= m, n <= 100).

The last line of the test case contains two zeroes, it should not be processed.


Output

For each pair of integers in each test case, output its number followed by A(n, m) mod t. Use format shown in the sample output.

Two consecutive cases should be separated by a single blank line. No blank line should be produced after the last test case.


Sample Input

233 32 71 180 021 11 21 30 0

Sample Output

Case 1: 1Case 2: 2Case 3: 0Case 1: 0Case 2: 0Case 3: 0


Author: Andrew Stankevich
Source: Andrew Stankevich's Contest #6
Submit    Status
#include <iostream>#include <cstring>#include <cstdio>using namespace std;typedef long long ll;#include <cmath>ll phi(ll n){    int m = sqrt(n + 0.5);    ll ans = n;    for(int i=2;i<=m;i++)        if(n%i==0)    {        ans = ans / i * (i - 1);        while(n%i==0) n/=i;    }    if(n>1) ans=ans/n*(n-1);    return ans;}ll pow(ll a, ll b, ll m){    ll ret = 1;    for(a%=m;b;b>>=1,a=a*a%m) if(b&1) ret=ret*a%m;    return ret;}ll t,n,m;ll gao(ll n, ll b){    if(n==1) return 2;    if(n==2) return 4;    if(n==3) return 16;    if(n==4) return 65536;    ll d = phi(b);    return pow(2, d + gao(n-1, d), b);}ll gao(ll b){    if(b==1) return 0;    ll d = phi(b);    return pow(2, d+gao(d), b);}int main(){    int re; cin>>re;    bool blank=false;    while(re--)    {        if(blank) puts("");        blank=true;        cin>>t;        int ca=1;        ll x = gao(t);        while(cin>>n>>m)        {            if(n==0&&m==0) break;            ll ans = 0;            if(n==1)            {                ans = 2 * m % t;            } else if(n==2) {                ans = pow(2, m, t);            } else if(n==3) {                ans = gao(m, t) % t;            }            else            {                if( m==1) ans=2;                else if(m==2) ans=4;                else if(n==4&&m==3) ans=65536;///gao(4,t);                else ans = x;            }            ans %= t;            printf("Case %d: %lld\n", ca++, ans);        }    }}


0 0