1.与运算(&)
参加运算的两个数据,按二进制位进行“与”运算。
运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1;
即:两位同时为“1”,结果才为“1”,否则为0
例如:3&5 即 0000 0011 & 0000 0101 = 0000 0001 因此,3&5的值得1。
例如:9&5 即 0000 1001 (9的二进制补码)&00000101 (5的二进制补码) =00000001 (1的二进制补码)可见9&5=1。
2.或运算(|)
参加运算的两个对象,按二进制位进行“或”运算。
运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1;
即 :参加运算的两个对象只要有一个为1,其值为1。
例如:3|5 即 0000 0011 | 0000 0101 = 0000 0111 因此,3|5的值得7。
例如:9|5可写算式如下: 00001001|00000101 =00001101 (十进制为13)可见9|5=13
3.异或运算(^)
参加运算的两个数据,按二进制位进行“异或”运算。
运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0;
即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。
例如:9^5可写成算式如下: 00001001^00000101=00001100 (十进制为12)可见9^5=12
例题:1073. 多选题常见计分法(20)-PAT乙级真题
分析:此题00001代表a正确,00010代表b正确,依次类推,记录答案,巧妙地用了与或异或运算
题解:
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int main(){
int n,m,optnum,truenum,temp,maxcnt=0;
int hash[]={1,2,4,8,16},opt[1010][110]={0};
char c;
cin>>n>>m;
vector<int>fullscore(m),trueopt(m);
vector<vector<int> > cnt(m,vector<int>(5));//vector二维数组
for(int i=0;i<m;i++){
cin>>fullscore[i]>>optnum>>truenum;
for(int j=0;j<truenum;j++){
scanf(" %c",&c);
trueopt[i]+=hash[c-'a'];
}
}
for(int i=0;i<n;i++){
double grade=0;
for(int j=0;j<m;j++){
getchar();
scanf("(%d",&temp);
for(int k=0;k<temp;k++){
scanf(" %c)",&c);//此处输入若没有括号则不读入
opt[i][j]+=hash[c-'a'];
}
int el =opt[i][j]^trueopt[j];
if(el){
if((opt[i][j]|trueopt[j])==trueopt[j]){
grade+=fullscore[j]*1.0/2;
}
if(el){
for(int k=0;k<5;k++)
if(el&hash[k])cnt[j][k]++;//i代表第几个人,j代表第几个题,k代表第几个选项
}
}
else{grade+=fullscore[j];
}
}
printf("%.1f\n",grade);
}
for(int i=0;i<m;i++)
for(int j=0;j<5;j++)
maxcnt=maxcnt>cnt[i][j]?maxcnt:cnt[i][j];
if(maxcnt==0){
printf("Too simple\n");
}
else {
for(int i=0;i<m;i++){
for(int j=0;j<cnt[i].size();j++){
if(maxcnt==cnt[i][j])//输出错得最多的题
printf("%d %d-%c\n",maxcnt,i+1,'a'+j);
}
}
}
return 0;
}