AOJ1250 Leaky Cryptography

問題リンク Leaky Cryptography

  • 概要

整数N1〜N8とチェックサムN9が16進数表記で与えられる。これらは32ビット整数である。
Σ(Ni xor K) = N9 xor K
を満たすような32ビット整数Kを16進数表記で求めよ。

  • 解法

Kを0ビット目から31ビット目まで順番に決めていきます。
iビット目を0にしたとき、(8個のNのiビット目の合計 + i-1ビット目からの繰り上がり)と、(N9と0のxorの結果)が合えばiビット目に0を採用することができます。これを全てのビットに対して繰り返します。
出来上がったKをlongにして、%hで出力すると16進数表記に簡単にできます。

  • ソース
import java.util.Scanner;

//Leaky Cryptography
public class AOJ1250 {

	int[][] a;
	int[] cs, t;
	char[] key;
	
	boolean dfs(int k, int c){
		if(k==-1)return true;
		key[k] = '0';
		int x = c;
		for(int i=0;i<8;i++)x+=a[i][k];
		if(x%2==cs[k]){
			if(dfs(k-1, x/2))return true;
		}
		key[k] = '1';
		x = c;
		for(int i=0;i<8;i++)x+=(a[i][k]+1)%2;
		if(x%2==(cs[k]+1)%2){
			if(dfs(k-1, x/2))return true;
		}
		return false;
	}
	
	int[] make(String s){
		int[] r = new int[32];
		long x = Long.parseLong(s, 16);
		int i = 31;
		while(x>0){
			r[i--] = (int) (x%2);
			x>>=1;
		}
		return r;
	}
	
	void run(){
		Scanner sc = new Scanner(System.in);
		int T = sc.nextInt();
		while(T--!=0){
			a = new int[8][32];
			for(int i=0;i<8;i++)a[i] = make(sc.next());
			cs = make(sc.next());
			key = new char[32];
			dfs(31, 0);
			long l = Long.parseLong(new String(key), 2);
			System.out.println(String.format("%h", l));
		}
	}
	
	public static void main(String[] args) {
		new AOJ1250().run();
	}
}