直接枚举,然后用位运算计算二进制表示时1的个数。代码:
/* ID: xincaor1 LANG: JAVA TASK: hamming */ import java.util.*; import java.math.*; import java.io.*; public class hamming { public static boolean check(int a,int b,int d) { int x; x= a^b; x= (x&0x55555555) + ((x >> 1)&0x55555555); x= (x&0x33333333) + ((x >> 2)&0x33333333); x= (x&0x0F0F0F0F) + ((x >> 4)&0x0F0F0F0F); x= (x&0x00FF00FF) + ((x >> 8)&0x00FF00FF); x= (x&0x0000FFFF) + ((x >> 16)&0x0000FFFF); if (x >= d) return true; else return false; } public static void main (String[] args) throws IOException{ int[] ans = new int[200]; int n,b,d,k; Scanner cin = new Scanner(new FileReader("hamming.in")); PrintWriter out = new PrintWriter(new BufferedWriter( new FileWriter("hamming.out"))); n=cin.nextInt(); b=cin.nextInt(); d=cin.nextInt(); k=0; for(int i=0;i<(int)Math.pow(2.0,b*1.0);i++) { int j; for(j=0;j<k;j++) { if(check(ans[j],i,d)==false) break; } if(j==k) ans[k++]=i; if(k==n) break; } //System.out.print(ans[0]); out.print(ans[0]); for(int i=1;i<k;i++) { if(i%10==0) { //System.out.println(); //System.out.print(ans[i]); out.println(); out.print(ans[i]); } else { //System.out.print(" "+ans[i]); out.print(" "+ans[i]); } } out.println(); cin.close(); out.close(); } }
matrix67有关位运算的讲解实在是太好了,终于派上用场了,现在摘取一些,方便以后查阅。
Pascal和C中的位运算符号 下面的a和b都是整数类型,则:C语言 | Pascal语言-------+-------------a & b | a and ba | b | a or ba ^ b | a xor b ~a | not aa << b | a shl ba >> b | a shr b
一个看起来非常诡异的swap过程:procedure swap(var a,b:longint);begin a:=a xor b; b:=a xor b; a:=a xor b;end;
一些常见的二进制位的变换操作。 功能 | 示例 | 位运算----------------------+---------------------------+--------------------去掉最后一位 | (101101->10110) | x shr 1在最后加一个0 | (101101->1011010) | x shl 1在最后加一个1 | (101101->1011011) | x shl 1+1把最后一位变成1 | (101100->101101) | x or 1把最后一位变成0 | (101101->101100) | x or 1-1最后一位取反 | (101101->101100) | x xor 1把右数第k位变成1 | (101001->101101,k=3) | x or (1 shl (k-1))把右数第k位变成0 | (101101->101001,k=3) | x and not (1 shl (k-1))右数第k位取反 | (101001->101101,k=3) | x xor (1 shl (k-1))取末三位 | (1101101->101) | x and 7取末k位 | (1101101->1101,k=5) | x and (1 shl k-1)取右数第k位 | (1101101->1,k=4) | x shr (k-1) and 1把末k位变成1 | (101001->101111,k=4) | x or (1 shl k-1)末k位取反 | (101001->100110,k=4) | x xor (1 shl k-1)把右边连续的1变成0 | (100101111->100100000) | x and (x+1)把右起第一个0变成1 | (100101111->100111111) | x or (x+1)把右边连续的0变成1 | (11011000->11011111) | x or (x-1)取右边连续的1 | (100101111->1111) | (x xor (x+1)) shr 1去掉右起第一个1的左边 | (100101000->1000) | x and (x xor (x-1))二进制中的1有奇数个还是偶数个var x:longint;begin readln(x); x:=x xor (x shr 1); x:=x xor (x shr 2); x:=x xor (x shr 4); x:=x xor (x shr 8); x:=x xor (x shr 16); writeln(x and 1);end.
计算二进制中的1的个数x := (x and $55555555) + ((x shr 1) and $55555555); x := (x and $33333333) + ((x shr 2) and $33333333); x := (x and $0F0F0F0F) + ((x shr 4) and $0F0F0F0F); x := (x and $00FF00FF) + ((x shr 8) and $00FF00FF); x := (x and $0000FFFF) + ((x shr 16) and $0000FFFF);
二分查找32位整数的前导0个数int nlz(unsigned x){ int n; if (x == 0) return(32); n = 1; if ((x >> 16) == 0) {n = n +16; x = x <<16;} if ((x >> 24) == 0) {n = n + 8; x = x << 8;} if ((x >> 28) == 0) {n = n + 4; x = x << 4;} if ((x >> 30) == 0) {n = n + 2; x = x << 2;} n = n - (x >> 31); return n;}