TopCoder SRM 147 DIV 1 Medium 練習

問題

立方体の惑星に龍が六匹、それぞれの面に棲んでいる。

食事の際、龍はそれぞれ隣り合った四面にいる龍の食事を盜もうとして、結果としてそれぞれの食事の四分の一を盜んでくる。

最初にそれぞれの龍が食事を持っている量が与えられるので、指定の回数だけ全員が盜みを繰り返したあと、上の面に乗っている龍が持っている食事の量を求めなさい。

まあやるだけ。分数の実装がめんどくさかった。

四面から四分の一盜ってくるんだけど、逆に四面からそれぞれ四分の一盜られるので、そこに気付けば計算は楽。

using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.Generic;

public class Fraction {
    public long p, q;    // p/q
    public Fraction(long p_, long q_)
    {
        p = p_;
        q = q_;
        Reduction();
    }
    public Fraction(Fraction f, long q_)
    {
        p = f.p;
        q = f.q * q_;
        Reduction();
    }
    private static long gcd(long a, long b)
    {
        return b == 0 ? a : gcd(b, a % b);
    }
    public void Reduction()
    {
        long t = gcd(p, q);
        p /= t;
        q /= t;
    }
    public static Fraction Add(Fraction l, Fraction r)
    {
        long t = gcd(l.q, r.q);
        long np, nq;
        np = l.p * (r.q / t); nq = l.q * (r.q / t);
        np += r.p * (l.q / t);
        return new Fraction(np, nq);
    }
    public override string ToString()
    {
        Reduction();
        if (q == 1)
            return p.ToString();
        return p + "/" + q;
    }
}

public class Dragons {
    public string snaug(int[] initialFood, int rounds) {
        Fraction[] foods = new Fraction[initialFood.Length];

        for (int i = 0; i < initialFood.Length; ++i)
            foods[i] = new Fraction(initialFood[i], 1);

        for (int i = 0; i < rounds; ++i)
        {
            Fraction[] next = new Fraction[initialFood.Length];
            for (int j = 0; j < initialFood.Length; ++j)
            {
                int pos = j | 1;
                next[j] = new Fraction(0, 1);
                for (int k = 1; k <= 4; ++k)
                {
                    int t = (pos + k) % 6;
                    next[j] = Fraction.Add(next[j], new Fraction(foods[t], 4));
                }
            }
            next.CopyTo(foods, 0);
        }
        return foods[2].ToString();
    }
}