C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で各行から数値を選択し、XORが0より大きくなるようにできるかを判定する方法

問題の概要

N × M の2次元配列が与えられたとします。この課題は、各行から1つずつ数値を選択し、選んだ要素のXOR(排他的論理和)が0以外(0より大きい値)になるようにできるかどうかを判定することです。例えば、次のような行列を考えてみましょう。

777
10107

この場合、2行目の最後の要素以外が7と10で異なるため、XORを計算すると0以外の値になります。

解法のアプローチ

この問題の解法は非常にシンプルです。以下の手順で判定できます。

  1. まず、各行の最初の列の要素のXORを計算します。その結果が0以外であれば、答えは「可能」です。
  2. XORが0だった場合は、いずれかの行に2つ以上の異なる要素が含まれているかどうかを確認します。含まれていれば、その行で選ぶ要素を変更することでXORを0以外にできるため、やはり「可能」です。
  3. 上記のどちらの条件も満たされない場合は、「不可能」です。

考え方のポイント

なぜこの判定で正しいのでしょうか。各行の最初の列の要素のXORがすでに0以外であれば、そのまま選択すればよいからです。一方、XORが0の場合でも、ある行に異なる要素が2つ以上存在すれば、そのうちの1つに選び替えることでXORの値は必ず変化します。逆に、すべての行が同一の値のみで構成されており、かつ最初の列のXORが0であれば、どのように選んでもXORは0のままになってしまいます。

サンプルコード

#include<iostream>
using namespace std;
#define N 2
#define M 3
bool isXORnonZero(int matrix[N][M]) {
    int xor_value = 0;
    for (int i = 0; i < N; i++) {
        xor_value ^= matrix[i][0];
    }
    if (xor_value != 0)
        return true;
    for (int i = 0; i < N; i++) {
        for (int j = 1; j < M; j++) {
            if (matrix[i][j] != matrix[i][0])
                return true;
        }
    }
    return false;
}
int main() {
    int mat[N][M] = {
        { 7, 7, 7 },
        { 10, 10, 7 }
    };
    if (isXORnonZero(mat))
        cout << "XOR has non-zero value";
    else
        cout << "XOR has zero value";
}

出力

XOR has non-zero value

まとめ

このアルゴリズムの計算量はO(N × M)です。行列全体を最大1回走査するだけで判定が完了するため、非常に効率的です。XORの性質(同じ値同士のXORは0になる、異なる値を1つ選び替えると結果が必ず変化する)を理解していれば、直感的に導き出せる解法と言えます。


  1. C++で数値が2つの過剰数の和として表現できるか判定する方法

    ある整数 n が与えられたとき、それを2つの過剰数の和として表現できるかどうかを判定します。表現できる場合はその2つの数を出力し、できない場合は -1 を出力します。 ここで「過剰数(Abundant Number)」とは、その数自身を除く約数(真の約数)の総和 sum(n) が、元の数の値より大きくなるような数のことです。例えば 12 の真の約数は 1, 2, 3, 4, 6 で、その総和は 16 となり 12 より大きいため、12 は過剰数です。 解法のアプローチ この問題を解くには、まず N 未満のすべての過剰数をあらかじめセット(set)に格納しておきます。次に、与えられた数 n に

  2. C++で数値がミステリーナンバーかどうかを判定する方法

    ミステリーナンバーとは?ここでは、ある数値がミステリーナンバー(Mystery Number)であるかどうかを判定する方法を解説します。ミステリーナンバーとは、互いに桁を逆にした(反転させた)2つの数の和として表すことができる数のことです。例えば、121 は「29 + 92」と表すことができます。29 と 92 は互いに数字を逆順にした関係にあるため、121 はミステリーナンバーだと言えます。アルゴリズムの考え方判定を行うには、1 から n/2 までの各数値 i について、その逆順の数 j を求め、「i + j == n」が成り立つかどうかをすべてのペアに対して確認します。条件を満たすペアが1