Project Euler 684 Inverse Digit Sum

解法

各桁の数の和がxとなるような最小の整数 s(x) は必ず一番上の桁以外は全て9となる。
よって s(x) は以下のようになる。

 
\begin{eqnarray}
s(x) = (x\%9) \times10^{\lfloor \frac{x}{9}  \rfloor} + 10^{\lfloor \frac{x}{9}  \rfloor} -1

\end{eqnarray}

s(x) の和 S(x) を考える。
S(20)=1074だが、これは以下のようにして求まる。

s(1)    =           1
...
s(9)    =           9
s(10)   =       1   9
s(11)   =       2   9
...
s(18)   =       9   9
s(19)   =   1   9   9
s(20)   =   2   9   9

 S(x) = (x\%9)\times 999...999 + 45 \times 10...0 + (45+81) \times 10...000 + (45+81\times 2) \times 10...000 + ...

これは式変形の力によって以下の式で求まる。


 
\begin{eqnarray}

S(x) = 3(2^{\lfloor \frac{x}{9} \rfloor+1} \times 5^{\lfloor \frac{x}{9} \rfloor}-5-3 (\lfloor \frac{x}{9} \rfloor-1))
+
(10^{\lfloor \frac{x}{9} \rfloor}-1)(x\%9)+10^{\lfloor \frac{x}{9} \rfloor}(x\%9+1)(x\%9)/2

\end{eqnarray}
よって S(x) が O(1) で求まるので、あとは各フィボナッチ数について計算すれば良い。

use self::mod_int::ModInt;

const MOD: u128 = 1e9 as u128 + 7;

fn main() {
    let mut f: Vec<u128> = vec![0, 1];
    let mut ans = ModInt(0);
    for i in 2..91 {
        let fi = f[i - 1] + f[i - 2];
        f.push(fi);
        ans += big_s2(fi);
    }
    println!("{}", ans.0);
}

fn big_s(x: u128) -> u128 {
    let nines = x / 9;
    let remain = x % 9;
    let mut sum = 0;
    sum += (remain + 1) * remain / 2;
    let mut upper = remain;
    for _ in 0..nines {
        sum *= 10;
        sum += upper * 9;
        sum += (9 + 1) * 9 / 2;
        upper += 9;
    }
    sum
}

fn big_s2(x: u128) -> ModInt<u128> {
    let nines = x / 9;
    let sum = if nines > 0 {
        let r = nines - 1;
        (ModInt(2).pow(r + 2) * ModInt(5).pow(r + 1) - 5 - ModInt(3) * r) * 3
    } else {
        ModInt(0)
    };
    let remain = x % 9;
    let head =
        (ModInt(10).pow(nines) - 1) * remain + ModInt(10).pow(nines) * (remain + 1) * remain / 2;
    sum + head
}

pub mod mod_int {
    use super::MOD;
    use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};

    type Num = u128;

    #[derive(Clone, Copy)]
    pub struct ModInt<T: Copy + Clone>(pub T);

    impl Add<ModInt<Num>> for ModInt<Num> {
        type Output = ModInt<Num>;
        fn add(self, rhs: ModInt<Num>) -> ModInt<Num> {
            self + rhs.0
        }
    }

    impl Add<Num> for ModInt<Num> {
        type Output = ModInt<Num>;
        fn add(self, rhs: Num) -> ModInt<Num> {
            let mut t = rhs + self.0;
            if t >= MOD {
                t = t - MOD;
            }
            ModInt(t)
        }
    }

    impl Sub<Num> for ModInt<Num> {
        type Output = ModInt<Num>;
        fn sub(self, rhs: Num) -> ModInt<Num> {
            let rhs = if rhs >= MOD { rhs % MOD } else { rhs };
            let value = if self.0 < rhs { self.0 + MOD } else { self.0 };
            ModInt(value - rhs)
        }
    }

    impl Sub<ModInt<Num>> for ModInt<Num> {
        type Output = ModInt<Num>;
        fn sub(self, rhs: ModInt<Num>) -> ModInt<Num> {
            self - rhs.0
        }
    }

    impl AddAssign<Num> for ModInt<Num> {
        fn add_assign(&mut self, other: Num) {
            *self = *self + other;
        }
    }
    impl AddAssign<ModInt<Num>> for ModInt<Num> {
        fn add_assign(&mut self, other: ModInt<Num>) {
            *self = *self + other;
        }
    }

    impl SubAssign<Num> for ModInt<Num> {
        fn sub_assign(&mut self, other: Num) {
            *self = *self - other;
        }
    }

    impl SubAssign<ModInt<Num>> for ModInt<Num> {
        fn sub_assign(&mut self, other: ModInt<Num>) {
            *self = *self - other;
        }
    }

    impl Div<Num> for ModInt<Num> {
        type Output = ModInt<Num>;
        fn div(self, rhs: Num) -> ModInt<Num> {
            self * ModInt(rhs).pow(MOD - 2)
        }
    }

    impl Div<ModInt<Num>> for ModInt<Num> {
        type Output = ModInt<Num>;
        fn div(self, rhs: ModInt<Num>) -> ModInt<Num> {
            self / rhs.0
        }
    }

    impl DivAssign<Num> for ModInt<Num> {
        fn div_assign(&mut self, rhs: Num) {
            *self = *self / rhs
        }
    }
    impl DivAssign<ModInt<Num>> for ModInt<Num> {
        fn div_assign(&mut self, rhs: ModInt<Num>) {
            *self = *self / rhs
        }
    }

    impl Mul<ModInt<Num>> for ModInt<Num> {
        type Output = ModInt<Num>;

        fn mul(self, rhs: ModInt<Num>) -> ModInt<Num> {
            self * rhs.0
        }
    }
    impl Mul<Num> for ModInt<Num> {
        type Output = ModInt<Num>;

        fn mul(self, rhs: Num) -> ModInt<Num> {
            let t = (self.0 * rhs) % MOD;
            ModInt(t)
        }
    }

    impl MulAssign<Num> for ModInt<Num> {
        fn mul_assign(&mut self, rhs: Num) {
            *self = *self * rhs;
        }
    }

    impl MulAssign<ModInt<Num>> for ModInt<Num> {
        fn mul_assign(&mut self, rhs: ModInt<Num>) {
            *self = *self * rhs;
        }
    }

    impl ModInt<Num> {
        pub fn pow(self, e: Num) -> ModInt<Num> {
            let mut result = ModInt(1);
            let mut cur = self;
            let mut e = e;
            while e > 0 {
                if e & 1 == 1 {
                    result *= cur;
                }
                e >>= 1;
                cur *= cur;
            }
            result
        }
    }
}