C♯の勉強

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

TopCoder SRM 590: XorCards

public class XorCards {
    public long NumberOfSolution(int[,] matrix) {
        int n = matrix.GetLength(0);
        int m = matrix.GetLength(1);
        bool[] used = new bool[n];

        for (int i = 0; i < m; i++) {
            int target = -1;
            for (int j = 0; j < n; j++) {
                if (!used[j] && matrix[j, i] == 1) { target = j; break; }
            }
            if (target == -1) continue;
            used[target] = true;
            for (int j = 0; j < n; j++) {
                if (target == j) continue;
                if (matrix[j, i] == 0) continue;
                for (int k = 0; k < m; k++) {
                    matrix[j, k] ^= matrix[target, k];
                }
            }
        }
        int rank = 0;
        for (int i = 0; i < n; i++) {
            bool allZero = true;
            for (int j = 0; j < m - 1; j++) {
                if (matrix[i, j] == 1) { allZero = false; break; }
            }
            if (allZero) {
                if (matrix[i, m - 1] == 1) return 0; // No solution
            } else {
                rank++;
            }
        }
        return 1L << ((m - 1) - rank);
    }

    public long numberOfWays(long[] number, long limit) {
        const int MaxBit = 60;
        long ans = 0;
        int n = number.Length;
        limit ++;

        for (int i = 0; i <= MaxBit; i++) {
            if ((limit & (1L << i)) == 0) continue;
            var array = new int[MaxBit + 1, n + 1];
            for (int j = i ; j <= MaxBit; j++) {
                if (i == j) array[j, n] = 0;
                else array[j, n] = (limit & (1L << j)) != 0 ? 1 : 0;
                for (int k = 0; k < n; k++) {
                    array[j, k] = (number[k] & (1L << j)) != 0 ? 1 : 0;
                }
            }
            ans += NumberOfSolution(array);
        }

        return ans;
    }
}