ビット演算とバイナリ

序文

主にバイナリを使用して一部の操作を記録します。これは、効率的な問題解決に便利です。

基本的な操作とルール

まず、このビット演算の基本的な演算規則と、問題を解決するために使用できる基本的な規則について説明します。

& 手術

1&1 = 1

1&0 = 0

0&0 = 0

^操作

1 ^ 1 = 0

1 ^ 0 = 1

0 ^ 0 = 0

|操作

1 | 1 = 1

1 | 0 = 0

0 | 0 = 0

左右シフト操作

a << 1:aは1つ左にシフトされます

a >> 1:aが1つ右にシフトします

基本法

1.コンピューターが操作を実行するとき、それは本質的に二項操作を実行します。つまり、このプロパティを最大限に活用して、予期しない結果を達成することができます。

2.キャリーなしのKベースのK数の合計は0です。

3.現在の状態を保存するためにバイナリビットが1とXORされます

4. 2進数を減算すると、最小の1が0に変換されます

これを私たちの法1と組み合わせると、多くの非常に興味深い操作が発生します。
次に、いくつかの使用法を順番に紹介します。

場合

^コンピューティングのトリック

配列[1,1,2,2,3,3,4,5,5]などの要件を指定します

特定の番号を除いて、他のすべての番号はペアで表示されます。ここで、例の4のように、ペアで表示されない番号を見つけることができます。

スキーム1ハッシュ法

まず、ハッシュ法を考えるのは簡単ですが、この場合、空間の複雑さは明らかに良くなく、答えを知るためにハッシュ配列を一度トラバースする必要があります。

public class 位运算1 {
    
    

    public static void main(String[] args) {
    
    

        int[] a = new int[]{
    
    1,1,2,2,3,3,4,5,5};

        int[] hash = new int[a.length];

        for (int j : a) {
    
    
            hash[j]++;
        }

        for (int i = 0; i < hash.length; i++) {
    
    
            if(hash[i]==1){
    
    
                System.out.println(i);
            }
        }

    }

}

シナリオ2^操作

解の時間と空間は良くないので、この解を解きたい場合は、^操作を使用する必要があります。

以来:1 ^ 1 = 0 0 ^ 0 = 0

したがって、3と3がXORされる場合、結果は0でなければならないため、ペアのXORはすべて0になり、0と4のXORは当然4になります。

public class 位运算1 {
    
    

    public static void main(String[] args) {
    
    
        //找出不同
        int[] a = new int[]{
    
    1,1,2,2,3,3,4,5,5};

          int x = 0;
          for (int i : a) {
    
    
              x = x^i;
          }
          System.out.println(x);
    }

}

1であるビットの数を数えます

10進数を指定して、10進数の桁に1がいくつあるかを確認するように依頼します

たとえば、3–>011
には2つあります

ここには多くの解決策があるので、ここで一緒に話します。

対処する最も簡単な方法

同様に、この10進数を2進数に直接変換してから、1を数えることも簡単に考えられます。

public class 运算二 {
    
    
    public static void main(String[] args) {
    
    
        int a = 3;
        char[] chars = Integer.toString(a, 2).toCharArray();
        int count = 0;
        for (char aChar : chars) {
    
    
            if(aChar=='1'){
    
    
                count++;
            }
        }
        System.out.println(count);
    }
}

これは、考えるのが最も簡単なオプションの1つです。したがって、ここでは、実際にビット演算を使用してすばやく実行できます。

シフト操作を使用する

image.png

考え方はこんな感じで、書きやすいです。

public class 运算二 {
    
    
    public static void main(String[] args) {
    
    
        int a = 3;
        int count = 0;
        for (int i = 0;i<32;i++){
    
    
            //4个字节32位
            if((a&(1<<i)) == (1<<i)){
    
    
                count++;
            }
        }
        System.out.println(count);
    }
}

もちろん、ここでは左シフトを使用しているので、右にシフトしてもかまいません。

1つの魔法の使用を引く

前に書いたポイント3を思い出してください。
a=3などの数値の場合

image.png

public class 运算二 {
    
    
    public static void main(String[] args) {
    
    
        int a = 3;
        int count = 0;
        while (a!=0){
    
    
            a = a&(a-1);
            count++;
        }
        System.out.println(count);
    }
}

|動作状態の遷移

これ、前のトピックを覚えていますか?

状態圧縮+動的計画法(Blue Bridge Cup 2019 java group Aキャンディーの問題)

その中には非常に賢いことがあります。それは、次の単一のプリミティブグループを状態番号に変換することです。これはdpに便利です。

6 5 3  
1 1 2  
1 2 3  
1 1 3  
2 3 5  
5 4 2  
5 1 2  
6 5 3    状态压缩
		二进制  十进制
1 1 2   00011	3
1 2 3	00111	7
1 1 3	00101	5

私たちのコードはこのように機能します

w[i] |=(1<<k-1) ;

このwは私たちの状態を保存するためのものです。
そのとき、dpの意味は、現在の状態で必要なキャンディーの数です。

ここにdp配列の構築について少し説明します。このdpの値は常に保存されることを覚えておく必要があります。このキャンディー問題などの現在の最適なソリューションでは、最小数のパケットが必要です。最初に、最小および最大の単語、それはdpまたは貪欲でなければなりませんが、貪欲を理解する人は誰でも理解し、dp(0-1ナップサック問題または複数のナップサックなど)がこの数のパッケージを必要とすることを直接考慮しなければなりません。 be dp [i] = value値はパッケージの数である必要があり、次にこれが何であるか、そして値を決定または影響する変数である必要があります。したがって、ここで状態を保存する方法がわからない場合、最終的に作成するdpは次のようになる可能性が非常に高くなります。dp[] [] [] ... = value []の数は、キャンディーの数によって異なります。持ってる。

それで、これがどのように変換されるか、私は前にそれを明らかにしなかったので、ここでもう一度言います。
実際、これは非常に単純です。最後に実行したいのは
、0 0 0 0 0の形式のバイナリ形式です(もちろん、最後にコンピューター用に10進数に変換されるため、直接使用します。状態を表す数値)

最初にデータセットを確認します
112

0 0 0 0 0初期状態
その後、Eを取り、1〜1ビット左にシフトし
、OR演算を実行すると、
0 0 001が得られます。

別の1
または
000 0 1
の後に、2つの左シフト2-1ユニットが続き、ビット単位の演算が続きます

0 0 0 1 1

したがって、3は112の状態を表します。

したがって、ビット演算は依然として非常に巧妙です。
ブルーブリッジカップをプレイしたいのであれば、このタイプの状態圧縮を再生する可能性はまだ高いと思います。状態は圧縮されてからバックパックに入れられます。

バックパック問題についてもまとめているところですが、問題が多いので、1つ目は探索問題です。基本的には直接DFS、BFSは他に何も考えず、せいぜい2点考えます。それがdp問題である場合、最も価値のある問題、基本的にはdpであり、基本的にナップサック問題であるこれらのdp問題の変形があります。これまでに見た中で最も多いのは、完全なナップサック、0にすぎません。 -1つのナップサック、それからモデルを再設定し、スペースの最適化を行います。基本的にはそれだけです。残りはどうですか?実際の状況によって異なります。もちろん、まだいくつかの数学的な問題があります。結局のところ、ブルーブリッジカップはアルゴリズムの競争です。まだいくつかの数学の問題があります。数学をマスターする必要があります。理論ですが、暴力的で網羅的(つまり、バックトラック)である場合を除いて、基本的にはそれを見ると諦めます(マスター3つの主要なポイント、再帰的バックトラッキング、検索(DFS、BFS、バイセクション)、dp(8つのバックパック問題))そしてもちろん、これは私の現在の考えです。大きなボスがいる場合は、私にアドバイス(コメントエリア)
正直なところ、私はプロの競技者ではありません。

おすすめ

転載: blog.csdn.net/FUTEROX/article/details/123482918