POJ 3748(C++的16进制读法 %x)

内容目录

P党写几小时的程序 C++才几行……

首先P的位运算有上限2^30 此时 即便是 int64也会因为补码坑死人的

到1 shl 31时   int64 是负数 故 这个时候 不能shr 为多出好多位

造成以上结果的真正原因是 shl 和 shr 只支持到1 shl 30 (Longint)所以在int64或qword会出错 要自己写


C党读入方法 %x 表示 二进制

#include<cstdio>
using namespace std;
int r,x,y;
int main()
{
	scanf("%x,%d,%d",&r,&x,&y);
	r=r&(~(1<<x));
	r=r&(~(1<<y-2));
	r=r|(1<<(y-1))|(1<<(y));
	printf("%xn",r);


}

P党取到30的做法:

Program P3748;
const
// ordA=65;
   orda=97;
   ord0=48;
var
   s:string;
   r:qword;
   x,y:longint;
function turn2(c:char):longint;
begin
   if ord(c)>=orda then begin exit(ord(c)-orda+10); end
   else exit(ord(c)-ord0);
end;
function turn16(x:qword):longint;
begin
   if (x<>0) then
   begin
      turn16:=x and 15;
      x:=x shr 4;
      turn16(x);
      if turn16<=10 then write(turn16) else write(chr(turn16-10+orda));
   end;
end;
function cin:longint;
var
   i:longint;
   s1:string;
begin
   i:=1;
   while s[i]<>',' do inc(i);
   s1:=copy(s,1,i-1);
   val(s1,cin);
   delete(s,1,i);


end;

function cin16:qword;
var
   i,j:longint;
   s1:string;
begin
   i:=1;
   while s[i]<>',' do inc(i);
   s1:=copy(s,1,i-1);
   cin16:=0;
   for j:=1 to i-1 do
      cin16:=cin16 shl 4+turn2(s1[j]);
   delete(s,1,i);
end;


begin
   readln(s);
   r:=cin16;x:=cin;val(s,y);


   r:=r and (not (1 shl x));

   r:=r and (not (1 shl (y-2)));
   r:=r or (1 shl (y-1));
   r:=r or (1 shl y);
   turn16(r);
   writeln;

end.

更正AC版:

Program P3748;
const
// ordA=65;
   orda=97;
   ord0=48;
var
   s:string;
   r,k:qword;
   x,y,i:longint;
function turn2(c:char):longint;
begin
   if ord(c)>=orda then begin exit(ord(c)-orda+10); end
   else exit(ord(c)-ord0);
end;
function turn16(x:qword):longint;
begin
   if (x<>0) then
   begin
      turn16:=x and 15;
      x:=x div 16;
      turn16(x);
      if turn16<=10 then write(turn16) else write(chr(turn16-10+orda));
   end;
end;
function cin:longint;
var
   i:longint;
   s1:string;
begin
   i:=1;
   while s[i]<>',' do inc(i);
   s1:=copy(s,1,i-1);
   val(s1,cin);
   delete(s,1,i);
end;
function cin16:qword;
var
   i,j:longint;
   s1:string;
begin
   i:=1;
   while s[i]<>',' do inc(i);
   s1:=copy(s,1,i-1);
   cin16:=0;
   for j:=1 to i-1 do
      cin16:=cin16 shl 4+turn2(s1[j]);
   delete(s,1,i);
end;

function shl2(x:longint):qword;
var
   i:longint;
begin
   shl2:=1;
   for i:=1 to x do shl2:=shl2*2;

end;
begin
   readln(s);
   r:=cin16;x:=cin;val(s,y);


  r:=r and (not (shl2(x)));


   r:=r and (not (shl2(y-2)));

   r:=r or (shl2(y-1));
   r:=r or (shl2(y));
   turn16(r);
   writeln;

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))