一、二进制操作
算数位运算:
A=60(0011 1100)
B=13(0000 1101)
1.与(&):两个二进制数,同 1为 1,否则为 0。 A & B=12(0000 1100)
2.或(|):两个二进制数,同 0为 0,否则为 1。 A | B=61(0011 1101)
3.非 按位取反(~):对二进制每一位进行了一次取反操作,若二进制数位0,则变成1,否则变成0。
~A=195(1100 0011)
4、异或运算(∧):两个二进制数,同为0,异为1。
异或性质:对于异或一个非常重要的性质,对于一个值异或同一个值两次,则结果还是原值。
移位操作符:
1、左移<< :二进制中的左移一位就是十进制中乘二。
2、右移<< :二进制中的右移一位就是十进制中除以二,舍去余数。
二、二进制枚举
.原理:
1.利用的是二进制下n位长度的数有2^n,即有这么多种情况;
2.对一个二进制来说 1 代表取这个元素 0代表不取这个元素;
3.利用循环,选取符合条件的情况;
题目
problem A(异或):teacher Li
nefu 643
/*思路:输入第一个名字为 a,其他都为 b,然后每个 b 和 a 异或*/
**#include <iostream>
#include <bits/stdc++.h>
using namespace std;
char a[31],b[31];/*在main之外定义字符串,在字符串结尾'/0'之后的ASCII值才能自动清为 0*/
int main()
{
int n,i,j,l,flag=0;
while(scanf("%d",&n)!=-1)
{flag++;
scanf("%s",a);
for(i=1;i<=2*n-2;i++)/*除a之外还有2*n-2个名字*/
{ getchar();
scanf("%s",b);
l=strlen(b);
for(j=0;j<l;j++)
a[j]=a[j]^b[j];
}
printf("Scenario #%d\n",flag);
printf("%s\n\n",a);
}
return 0;
}**
problem B (异或):Find different
nefu 1172
```cpp
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,a,x,i;
while(scanf("%d",&n)!=EOF)
{scanf("%d",&a);
for(i=1;i<n;i++)
{
scanf("%d",&x);
a=a^x;
}
printf("%d\n",a);
}
return 0;
}
problem C:和为K–二进制枚举
nefu 1205
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,a[20],k,flag=0,i,j,sum;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<(1<<n);i++)
{ sum=0;
for(j=0;j<n;j++)
{
if(i&(1<<j))/*利用与符号判断,当结果不为 0 时,代表取这一位*/
sum=sum+a[j];
}
if(sum==k)
{
flag=1;printf("Yes\n");
break;
}
}
if(flag==0)
printf("No\n");
}
return 0;
}
problem D:陈老师加油-二进制枚举
nefu 1505
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t,i,j,flag1,flag2,sum,d;
while(scanf("%d",&t)!=EOF)
{
sum=0;
for(i=0;i<(1<<15);i++)
{ d=t;flag1=flag2=0;
for(j=0;j<15;j++)
{
if(i&(1<<j))
{d*=2;flag1++;}/*记录遇到加油站的次数*/
else
{
d--;flag2++;/*记录遇到十字路口的次数*/
if(d<=0)break;
}
}
if(flag1==5&&flag2==10&&d==0)
sum++;
}
printf("%d\n",sum);
}
return 0;
}
problem E:纸牌游戏-二进制-搜索
nefu 1518
#include <iostream>
#include <bits/stdc++.h>
int main()
{
int n,k,a[100],i,j,s,flag;
while(scanf("%d%d",&n,&k)!=EOF)
{for(i=0;i<n;i++)
scanf("%d",&a[i]);
flag=0;
for(i=0;i<(1<<n);i++)
{s=0;
for(j=0;j<n;j++)
{
if(i&(1<<j))
s=s+a[j];
}
if(s==k)
flag++;
}
printf("%d\n",flag);
}
return 0;
}
problem F:权利指数
nefu 1641
#include <iostream>
#include <bits/stdc++.h>
int main()
{
int t,n,i,j,a[20],flag[20],s[20],sum;
double m;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
m=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);m=m+a[i];}
memset(s,0,sizeof(s));/*使 s 数组初始值都为0*/
for(i=0;i<(1<<n);i++)
{ sum=0;
memset(flag,0,sizeof(flag));
for(j=0;j<n;j++)
{
if(i&(1<<j))
{sum=sum+a[j];flag[j]=1;}/*flag用来标记a[j]是否取过*/
}
if(sum<=m/2)
{
for(j=0;j<n;j++)
{
if(sum+a[j]>m/2&&flag[j]==0)
s[j]++;
}
}
}
for(i=0;i<n-1;i++)
printf("%d ",s[i]);
printf("%d\n",s[n-1]);
}
return 0;
}
problem G:趣味解题
nefu 1285
#include <iostream>
#include <bits/stdc++.h>
int main()
{
int t,m;
scanf("%d",&t);
for(m=0;m<t;m++)
{
int n;
double a[13],b[13],c[13],d[13],e[13];
int x,i,j,flag;
double p,ants;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%lf",&a[i]);
for(i=0;i<n;i++)
scanf("%lf",&b[i]);
for(i=0;i<n;i++)
scanf("%lf",&c[i]);
scanf("%d",&x);
for(i=0;i<n;i++)
{
e[i]=(1-a[i])*(1-b[i])*(1-c[i]);/*每道题错误的概率*/
d[i]=1-e[i];/*每道题正确的概率*/
}
ants=0;
for(i=0;i<1<<n;i++)
{ p=1;flag=0;
for(j=0;j<n;j++)
{
if(i&(1<<j))
{p=p*d[j];flag++;}
else
p=p*e[j];
}
if(flag==x)
ants=ants+p;
}
printf("%.4lf\n",ants);
}
return 0;
}