usaco 2.1.4

    技术2024-12-28  61

    直接枚举,然后用位运算计算二进制表示时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;}

     

     

    最新回复(0)