1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
//! Ackermann 関数。
use super::mod_pow;
use super::mod_tetration;
use mod_pow::ModPow;
use mod_tetration::ModTetration;
/// Ackermann 関数。
///
/// 与えられた $(a, b, n)$ に対して $A(a, b)\\bmod n$ を返す。
/// 自然数 $a$, $b$ に対して Péter--Ackermann 関数 $A(a, b)$ は次のように定義される。
/// - $A(0, b) = b+1$,
/// - $A(a+1,0) = A(a, 1)$,
/// - $A(a+1, b+1) = A(a, A(a+1, b))$.
///
/// $\\gdef{\\hyper}{\\operatorname{hyper}}$
/// 以下の性質が知られている。
/// $$ a\\gt 0 \\implies \\hyper\_a(2, b+3)-3. $$
/// ただし、$\\hyper\_a$ は $a$ 番目のハイパー演算子である。
///
/// # Idea
/// $a\\le 4$ までは [`mod_pow`] や [`mod_tetration`] を用いて簡単に求められる。
/// [`mod_tetration`] と同様に、指数部が十分大きくなると値が一定になるので、それを利用する。
///
/// $A(5, b) = \\hyper\_5(2, b+3)-3 = \\underbrace{{}^{{}^{{}^2\\cdots} 2} 2}\_{b+3\\text{ many}} - 3$
/// となるが、$A(5, 0)$ は現実的な値として求められる。
/// $$ \\begin{aligned}
/// A(5, 0) &= {}^{{}^2 2} 2 - 3 \\\\
/// &= {}^4 2 - 3 \\\\
/// &= 2^{2^{2^2}} - 3 \\\\
/// &= 2^{2^4} - 3 \\\\
/// &= 2^{16}-3 = 65533.
/// \\end{aligned} $$
///
/// 一方で、$A(5, 1)$ は次のようになる。
/// $$ \\begin{aligned}
/// A(5, 1) &= {}^{{}^{{}^2 2} 2} 2 - 3 \\\\
/// &= {}^{65536} 2 - 3 \\\\
/// &= \\underbrace{2^{2^{\\cdots^2}}}\_{65536\\text{ many}}-3.
/// \\end{aligned} $$
///
/// ここで [`mod_tetration`] の議論を思い出すと、${}^b a \\bmod{n}$ は $b\\ge 2\\log(n)$
/// であれば一定値となる。引数の型が [`u64`] である今、$b$ として意味があるのは高々
/// $2\\log(2^{64}) = 128$ 程度であり、$A(5, 1)$ はそれを十分に上回る。
/// すなわち、$A(5, 1)\\bmod n = A(4, 2\\log(n))\\bmod n$ として計算してしまってよい[^bd]。
///
/// さらに、$A(6, 0) = A(5, 1)$ などから、$a\\ge 6$ についても同様にでき、次のようにできる。
/// - $A(0, b) \\equiv b+1 \\pmod{n}$,
/// - $A(1, b) \\equiv b + 2 \\pmod{n}$,
/// - $A(2, b) \\equiv 2b + 3 \\pmod{n}$,
/// - $A(3, b) \\equiv 2^{b+3} - 3 \\pmod{n}$,
/// - $A(4, b) \\equiv {}^{b+3} 2 - 3 \\pmod{n}$,
/// - $A(5, 0) \\equiv 65533 \\pmod{n}$,
/// - $A(5, b) \\equiv A(4, 2\\log(n)) \\pmod{n}$ for $b\\ge 1$,
/// - $A(a, b) \\equiv A(4, 2\\log(n)) \\pmod{n}$ for $a\\ge 6$.
///
/// [^bd]: 32768-bit 整数を受け取るような状況ではよくなさそう。512-word
/// の多倍長整数と思うとそこそこ現実的な気もする? だとしても $A(5, 2)$ はもう現実的じゃなさそう。
///
/// [`mod_pow`]: fn.mod_pow.html
/// [`mod_tetration`]: fn.mod_tetration.html
///
/// # Complexity
/// |入力|時間計算量|
/// |---|---|
/// |$a\\le 2$ or $(a, b) = (5, 0)$|$O(1)$|
/// |$a=3$|$O(\\log(b))$|
/// |otherwise|$O(\\sqrt{n})$|
///
/// # Examples
/// ```
/// use nekolib::math::ModAckermann;
///
/// let n = 10_u64.pow(9);
/// assert_eq!(2_u64.mod_ackermann(5, n), 13);
/// assert_eq!(3_u64.mod_ackermann(7, n), 1_021);
/// assert_eq!(4_u64.mod_ackermann(2, n), 719_156_733);
/// assert_eq!(4_u64.mod_ackermann(3, n), 437_428_733);
/// assert_eq!(4_u64.mod_ackermann(8, n), 432_948_733);
/// assert_eq!(9_u64.mod_ackermann(9, n), 432_948_733);
/// ```
pub trait ModAckermann {
fn mod_ackermann(self, b: Self, n: Self) -> Self;
}
macro_rules! impl_uint {
($t:ty) => {
impl ModAckermann for $t {
fn mod_ackermann(self, b: Self, n: Self) -> Self {
let sub_3 = |z| match n {
1 => 0,
2 => 1 - z,
3 => z,
_ if z >= 3 => z - 3,
_ => z + n - 3,
};
match (self, b) {
(0, _) => (b + 1) % n,
(1, _) => (b + 2) % n,
(2, _) => (2 * b + 3) % n,
(3, _) => sub_3((2 as $t).mod_pow(b + 3, n)),
(4, _) => sub_3((2 as $t).mod_tetration(b + 3, n)),
(5, 0) => (65533_u128 % n as u128) as $t, // for u8
_ => sub_3((2 as $t).mod_tetration(n, n)),
}
}
}
};
( $($t:ty)* ) => { $(impl_uint!($t);)* };
}
impl_uint!(u8 u16 u32 u64 u128 usize);
#[test]
fn test() {
let n = 14_u64.pow(8);
let res: u64 = (0..=7).map(|a| a.mod_ackermann(a, n)).sum();
assert_eq!(res % n, 452_774_460);
}