C♯の勉強

C♯4.0 で TopCoder の過去問を解きます。

TopCoder SRM595: LittleElephantAndXor

public class LittleElephantAndXor {
    // dp[着目しているbit][A未満になったか][B未満になったか][C未満になったか] = パターン数
    public long getNumber(int A, int B, int C) {
        int largeBit = new[] { A, B, C }.Select(GetLargeBit).Max();

        var dp = new long[2, 2, 2];
        for (int i = 0; i <= largeBit; i++) {
            var next = new long[2, 2, 2];
            int bitA = ((A & (1 << i)) != 0) ? 1 : 0;
            int bitB = ((B & (1 << i)) != 0) ? 1 : 0;
            int bitC = ((C & (1 << i)) != 0) ? 1 : 0;
            for (int lessA = 0; lessA < 2; lessA++) {
                for (int lessB = 0; lessB < 2; lessB++) {
                    for (int lessC = 0; lessC < 2; lessC++) {
                        long val = 0;

                        for (int newBitA = 0; newBitA < 2; newBitA++) {
                            for (int newBitB = 0; newBitB < 2; newBitB++) {
                                int newBitC = newBitA ^ newBitB;
                                int newLessA = lessA;
                                int newLessB = lessB;
                                int newLessC = lessC;

                                if (bitA < newBitA && lessA == 0) continue;
                                if (bitB < newBitB && lessB == 0) continue;
                                if (bitC < newBitC && lessC == 0) continue;
                                if (bitA > newBitA) newLessA = 1;
                                if (bitB > newBitB) newLessB = 1;
                                if (bitC > newBitC) newLessC = 1;

                                if (i == 0) {
                                    val++;
                                } else {
                                    val += dp[newLessA, newLessB, newLessC];
                                }
                            }
                        }

                        next[lessA, lessB, lessC] = val;
                    }
                }
            }
            dp = next;
        }

        return dp[0, 0, 0];
    }

    private static int GetLargeBit(int A) {
        int largeBit = 0;
        for (int i = 0; i <= 31; i++) {
            if ((A & (1 << i)) != 0) {
                largeBit = i;
            }
        }
        return largeBit;
    }
}