2020年1月3日 林大OJ习题 位运算与二进制枚举

2020年1月3日 位运算与二进制枚举

林大OJ 643 teacher Li

字符串异或问题,思路就是把所有字符串的每个字符依次异或,字符对应得ASCII码也是一个数字,所以字符也可以去异或。
而且在二进制中,0与任何数异或都等于那个数本身。

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,i,j,k;
    k=0;
    while(~scanf("%d",&n)){
        char a[40],b[40];
        scanf("%s",a);
        for(i=1;i<2*n-1;i++){
            scanf("%s",b);
            for(j=0;j<strlen(b);j++)
                a[j]=a[j]^b[j];
        }
        printf("Scenario #%d\n",++k);
        printf("%s\n\n",a);
    }
    return 0;
}

林大OJ 1172 Find different

两个相同数字的异或值为0

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,ans,i;
    cin>>n;
    ans=0;
    for(int j=1;j<=n;j++){
        cin>>i;
        ans=ans^i;
    }
    cout<<ans<<endl;
    return 0;
}

林大OJ 1205 和为K–二进制枚举

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,i,f=1;
    long long k;
    while(cin>>n>>k)
    {
        getchar();
        int a[n+1];
        for(i=0; i<n; i++)
            cin>>a[i];
        for(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==k)
            {
                cout<<"Yes"<<endl;
                f=0;
                break;
            }
        }
        if(f==1)
        cout<<"No"<<endl;
    }
    return 0;
}

林大OJ 1285 趣味解题

重点在于概率的运算以及利用二进制枚举将其表示的过程

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int t,n,i,j,x;
    double a[15],b[15],c[15],ans,ac[15],wc[15];//ac[i]表示做对第i题的概率,wc[i]表示做不出第i题的概率
    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;
        ans=0;
        for(i=0;i<(1<<n);i++){
            int num=0;
            double p=1;
            for(j=0;j<n;j++){
                wc[j]=(1-a[j])*(1-b[j])*(1-c[j]);//3个人都不会做该题的概率,是团队做不出该题的概率
                ac[j]=(1-wc[j]);
                if(i&(1<<j)){
                    p=p*ac[j];
                    num++;//记录团队的ac题数
                }
                else{
                    p=p*wc[j];
                }
            }
            if(num==x)
                ans=ans+p;
        }
        printf("%.4lf\n",ans);
    }
    return 0;
}

林大OJ 1505 陈老师加油

陈老师的初始油量必须存到一个新的变量里,每次循环可能会有不符合条件的油量剩余,对下次循环带来影响。

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int t,ans=0,k1,k2,tmp;
    cin>>t;
    for(int i=0;i<(1<<15);i++){
        k1=k2=0;
        tmp=t;//初始油量存入临时变量t里
        for(int j=0;j<15;j++){
            if(i&(1<<j)){
                k2++;
                tmp*=2;
            }
            else{
                k1++;
                tmp-=1;
                if(tmp<=0)
                    break;
            }
        }
        if(k1==10 && k2==5 && tmp==0)
            ans++;
    }
    cout<<ans<<endl;
    return 0;
}

林大OJ 1518 纸牌游戏

#include <bits/stdc++.h>

using namespace std;

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

林大OJ 1641 权利指数

先选出任意个小团体,选出来后做好标记(flag=1),并保证他们的票数之和小于等于总票数的一半,之后在没被选出来的小团体(flag=0)中再选出任意一个小团体,设他的票数为a[j],若加上a[j]后票数之和大于总票数的一半,那么这个a[j]就是“关键加入者”,则他的权利指数+1。

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int t,n,a[21],b[21],flag[21],k,i,j;
    cin>>t;
    for(k=1;k<=t;k++){
        memset(b,0,sizeof(b));
        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 x1=0;
            memset(flag,0,sizeof(flag));
            for(j=0;j<n;j++){
                if(i&(1<<j)){
                    x1+=a[j];
                    flag[j]=1;
                }
            }
            if(x1<=(sum/2)){
                for(j=0;j<n;j++){
                    if(x1+a[j]>(sum/2) && flag[j]==0)
                        b[j]++;
                }
            }
        }
        for(i=0;i<n-1;i++)
            cout<<b[i]<<" ";
        cout<<b[n-1]<<endl;
    }
    return 0;
}

林大OJ 1665 四糸乃买花–二进制枚举

只要你写着四糸乃,我就必须得做出来!!

本题就是裸的二进制枚举,有两个需要注意的地方:一是花钱数小于等于现有钱数才能去买,二是因为题目要求不能一朵花不买,所以从1开始枚举,因为不能全部买走,所以枚举到2的n次幂-2(2的n次幂-1为全选)。然后就枚举情况,对所有满足条件的情况答案数++,最后输出答案数即可。

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,a[23],ans=0,i,j;
    long long w;
    cin>>n;
    getchar();
    for(i=0;i<n;i++)
        cin>>a[i];
    getchar();
    cin>>w;
    for(i=1;i<(1<<n)-1;i++){//因为题目要求不能一朵花不买,所以从1开始枚举,因为不能全部买走,所以枚举到2的n次幂-2(2的n次幂-1为全选)
        int num=0;//记录买花数
        int sum=0;//记录买花花的总钱数
        for(j=0;j<n;j++){
            if(i&(1<<j)){
                sum+=a[j];
                num++;
                if(w==0) break;
            }
        }
        if(num%4==0 && (w-sum)%4==0&&(w-sum)>=0)//剩下的钱必须为正数
            ans++;
    }
    cout<<ans<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值