二进制枚举

一、二进制操作
算数位运算:
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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值