Problem:
Score : 800 points

Problem Statement

For a positive integer n, we denote the integer obtained by reversing the decimal notation of n (without leading zeroes) by rev(n). For example, rev(123) = 321 and rev(4000) = 4.

You are given a positive integer D. How many positive integers N satisfy rev(N) = N + D?

Constraints

D is an integer.

1 ≤ D < 10^9

Input

Input is given from Standard Input in the following format:

D

Output

Print the number of the positive integers N such that rev(N) = N + D.

Sample Input 1

63

Sample Output 1

2

There are two positive integers N such that rev(N) = N + 63: N = 18 and 29.

Sample Input 2

75

Sample Output 2

0

There are no positive integers N such that rev(N) = N + 75.

Sample Input 3

864197532

Sample Output 3

1920

Solution in Rust (1.15.1) (judge verdict: Accepted)

use std::io::*;
use std::str::FromStr;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

#[allow(dead_code)]
fn naive(d: i64) -> i64 {
    let mut ans = 0;
    for i in 1..100000 {
        let mut v = i;
        let mut rev = 0;
        while v > 0 {
            rev = rev * 10 + v % 10;
            v /= 10;
        }
        if rev == i + d {
            ans += 1;
            // println!("{}", i);
        }
    }
    ans
}

fn get_digit(v: i64, digit: usize) -> i64 {
    let mut v = v;
    for _ in 0..digit {
        v /= 10;
    }
    v % 10
}

fn calc(
    memo: &mut Vec<Vec<Vec<i64>>>,
    d: i64,
    max_digit: usize,
    upper_digit: usize,
    lower_digit: usize,
    upper_carry: i64, // 0, 1
    lower_carry: i64, // 0, 1
) -> i64 {
    if upper_digit < lower_digit {
        return if lower_carry == upper_carry { 1 } else { 0 };
    } else if upper_digit == lower_digit {
        return if get_digit(d, upper_digit) + lower_carry - upper_carry * 10 != 0 {
            0
        } else if max_digit == upper_digit {
            9
        } else {
            10
        };
    }
    if memo[upper_digit][upper_carry as usize][lower_carry as usize] != -1 {
        return memo[upper_digit][upper_carry as usize][lower_carry as usize];
    }
    let mut ret = 0;
    for u in 0..10 {
        if max_digit == upper_digit && u == 0 {
            continue;
        }
        for l in 0..10 {
            let mut rhs_lower = l + get_digit(d, lower_digit) + lower_carry;
            let mut nlower_carry = 0;
            if rhs_lower >= 10 {
                rhs_lower -= 10;
                nlower_carry = 1;
            }
            let mut rhs_upper = u + get_digit(d, upper_digit) - upper_carry * 10;
            let mut nupper_carry = 0;
            if rhs_upper == l - 1 {
                rhs_upper += 1;
                nupper_carry = 1;
            }
            if rhs_lower != u || rhs_upper != l {
                continue;
            }
            ret += calc(
                memo,
                d,
                max_digit,
                upper_digit - 1,
                lower_digit + 1,
                nupper_carry,
                nlower_carry,
            );
        }
    }
    memo[upper_digit][upper_carry as usize][lower_carry as usize] = ret;
    ret
}

fn solve(d: i64) -> i64 {
    let mut ans = 0;
    'outer_loop: for i in 0..30 {
        for j in i + 1..30 {
            if get_digit(d, j) != 0 {
                continue 'outer_loop;
            }
        }
        let mut memo = vec![vec![vec![-1; 2]; 2]; 30];
        ans += calc(&mut memo, d, i, i, 0, 0, 0);
    }
    ans
}

fn main() {
    let d = read::<i64>();
    println!("{}", solve(d));
    // println!("{}", naive(d));
}

#[test]
fn test() {
    for i in 1..1000 {
        println!("{} {} {}", i, solve(i), naive(i));
        assert!(solve(i) == naive(i));
    }
}