大一寒假集训(4)----二进制枚举

大一寒假集训(4)----二进制枚举nefu

序:二进制枚举原理

(1)算术位运算:在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(2)二进制位移操作符:
在这里插入图片描述
二进制枚举
在这里插入图片描述

1. 和为K–二进制枚举 nefu 1205

在这里插入图片描述

#include<bits/stdc++.h>

using namespace std;

int main()
{
    int n,k;
    int r;
    int a[25];
    while (cin>>n>>k)
    {
        r=0;
        for (int i=0;i<n;i++)
            cin>>a[i];
        for (int i=0;i<(1<<n);i++)//若n为5,i为长度为5的01串,i代表的是不同的位置如011001,取的是1对应的a[j]的位置,
        {
            int sum=0;
            for (int j=0;j<n;j++)
                {
                    if (i&(1<<j))//&表示取余,同为1,结果为1,<<左移
                    sum+=a[j];
                }
                if (k==sum)
                {
                    r=1;
                    printf("Yes\n");
                    break;
                }

        }
        if (r==0)
            printf("No\n");
    }
    return 0;
}

2.陈老师加油-二进制枚举 nefu 1505

第一重循环的左移15位是因为一共需要15位的01串.0,1分别代表路口和加油站(也可反过来)。此题中无需k来判断是否没油,因为题中条件为恰好没油。

#include <iostream>

using namespace std;

int main()
{
    int t;
    while (cin>>t)
    {
        int sum=0;
        for (int i=0;i<(1<<15);i++)//1为加油站,0为路口
        {
            int s1=0;//加油站
            int s2=0;//路口//初始化!!
            int ans=t;
            //int k=0;
            for (int j=0;j<15;j++)
            {
                if (i&(1<<j))
                    {
                        s1++;
                        ans*=2;
                    }
                else
                {
                    s2++;
                    ans-=1;
                    if (ans<=0)
                     break;

                }
            }
            if (s1==5&&s2==10&&ans==0)//题中为正好没油,所以无需k
                sum++;
        }
        cout<<sum<<endl;
    }
    return 0;
}

3.纸牌游戏-二进制-搜索 nefu 1518

此题与第三题十分相似

#include<bits/stdc++.h>


using namespace std;

int main()
{
    int n,p;
    int a[25];
    while (cin>>n>>p)
    {
        for (int i=0;i<n;i++)
            cin>>a[i];
            int ans=0;
        for (int i=0;i<(1<<n);i++)
        {
            int sum=0;
            for (int j=0;j<n;j++)
            {
                if (i&(1<<j))
                {
                    sum+=a[j];
                }
            }
                if (sum==p)
                    {
                        ans++;
                    }

        }
        printf("%d\n",ans);
    }

    return 0;
}

4.Find different nefu 1172

异或一个非常重要的性质:对于一个值异或同一个值两次,则结果还是原值。
在c/c++中异或用 ^表示。

#include<bits/stdc++.h>


using namespace std;

int main()
{

    int n;
    int a;
    while (scanf("%d",&n)!=EOF)
    {
        int sum=0;
      while (n--)
      {
          scanf("%d",&a);
          sum=sum^a;//异或
      }
        printf("%d\n",sum);
    }

    return 0;
}

5.teacher Li nefu 643

1.c++/c 中都可用str.length()、str.size()、sizeof(str),都是用于求string类对象的成员函数
2.c++中有max min 函数可直接使用
3.name1.c_str( )可直接输出string 类字符串
4.C++中 ios::sync_with_stdio(false); 可提高cin 与cout的效率

#include<bits/stdc++.h>
//异或
using namespace std;
//而且在二进制中,0与任何数异或都等于那个数本身。
int main()
{
    string name1;
    int n;
    string name2;
    int r=1;//测试组数
    int l1,l2;
    while (cin>>n)
    {
        cin>>name1;
        l1=name1.length();//先输入一个名字,异或
        n=n*2-2;
        for (int i=0;i<n;i++)
        {
            cin>>name2;
            l2=name2.length( );
            for (int j=0;j<max(l1,l2);j++)//使用最长的长度
                name1[j]=name1[j]^name2[j];//异或
        }
        printf("Scenario #%d\n",r);
        r++;
        printf("%s\n\n",name1.c_str());
    }
    return 0;
}

6.权利指数 nefu 1641

1.memset (z,0,sizeof(z)) 注意初始化,本题有两次初始化!!
2.本题一开始一直未AC,找了半个小时bug才发现是for 语句后多了; :)我哭辽。。。。。。
3.注意格式要求。
4.单组输入。

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int t;
    int a[25];//每个团队的票数
    int b[25];//关键加入者次数
    int z[25];//记录未被选出来团队
    int i,j;
    cin>>t;
    for (int r=0; r<t; r++)
    {
        memset (b,0,sizeof(b));
        int n;//共有n个团队
        cin>>n;
        int sum=0;
        for (i=0; i<n; i++)
        {
            cin>>a[i];//输入票数
            sum+=a[i];//统计总票数
        }//
        for (i=0; i<(1<<n); i++)
        {
            int k=0;
            memset (z,0,sizeof(z));//注意初始化
            for (j=0; j<n; j++)
            {
                if (i&(1<<j))
                {
                    k+=a[j];
                    z[j]=1;
                }
            }
            if (k<=sum/2)
            {
                for (j=0; j<n; j++)
                {
                    if (a[j]+k>sum/2&&z[j]==0)//z[j]记录的是未被选中的数组,若满足此条件,则关键加入者次数加一。
                        b[j]++;
                }
            }
        }
        for (i=0; i<n-1; i++)
            printf("%d ",b[i]);
        printf("%d\n",b[n-1]);//注意格式
    }
    return 0;
}

7.趣味解题 nefu 1285

概率问题,注意三人都做对的概率算法

#include <bits/stdc++.h>

using namespace std;

int main()
{
    double a[15],b[15],c[15];
    double ac[15],wa[15];
    int t,n,x;
    int i,j;
    double y1,co,sum;
    cin>>t;
    while (t--)
    {
        cin>>n;
        for (i=0;i<n;i++)
            cin>>a[i];
        for (i=0;i<n;i++)
            cin>>b[i];
        for (i=0;i<n;i++)
            cin>>c[i];
        cin>>x;
        sum=0;
        for (i=0;i<(1<<n);i++)
        {
            y1=1;co=0;
            for (j=0;j<n;j++)
            {
                wa[j]=(1-a[j])*(1-b[j])*(1-c[j]);//1-(三人都做错的概率)
                ac[j]=1-wa[j];//做对的概率
                if (i&(1<<j))
                {
                    y1=y1*ac[j];
                    co++//计算做对的题数;
                }
                else y1=y1*wa[j];//概率公式
            }
            if (co==x)
             sum+=y1;
        }
        printf("%.4lf\n",sum);
    }
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值