位运算和二进制枚举2020.1.3

时光毁灭记忆、已成空白 提交于 2020-01-11 01:47:25

异或 A^B

两数不同才是1。
通常用于对二进制的特定一位进行取反,可以对两个数进行交换。
常用性质:A^B^B=A,即B^B=0,可以用作判断一个数出现的次数,0^A=A,并且可以用作字符串的比较。
异或也叫半加运算,其运算法则相当于 不带进位的二进制加法
一数异或同一个数两次,则结果还是原数,即 (a ^ b) ^ b = a
0异或任何数,结果都等于那个数,即 0 ^ a = a

与 A&B

同为1才是1。
通常用于二进制位操作,如一个数&1的结果就是取二进制的最末尾,可以用来判断整数奇偶。

左移 (<<) 乘2

右移(>>)除2

用1或0来判断取或者不取

Find different
题目翻译
Description
给出一个奇数n(1<=n<=10000001)。

给你一个含有n个数的数组:a[1],a[2],a[3] … a[n],他们都是正整数。

有n/2个数字出现两次,只有1个数字出现一次。

现在你需要指出只出现一次的那个数字。

Input
有多个测试用例,以EOF结束。

第一行是一个整数n。

第二行有n个整数a[1],a[2]…a[n]。

#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
	while(cin>>n)
	{
		int x1, xn;
		cin>>x1;
		for(int i=1; i<n; i++)
		{
			cin>>xn;
			x1 ^= xn;
		}
		cout<<x1<<endl;
	}
	return 0;
}

和为K–二进制枚举

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int i,j,n,k,s,a[21];
int main()
{
    while(cin>>n>>k)
    {
        for(i=0;i<n;i++)
        cin>>a[i];
        int 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)
            {printf("Yes\n");flag=1;break;}
        }
        if(flag==0)printf("No\n");
    }
}

陈老师加油-二进制枚举

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    int ans; ans=0;
    for(int i=0;i<(1<<15);i++)
    {
        int k1=0,k2=0,tmp=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;
}

纸牌游戏-二进制-搜索

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int i,j,n,k,s,ans,a[21];
    while(cin>>n>>k)
    {
        for(i=0;i<n;i++)
        cin>>a[i];
        ans=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)
            ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

趣味解题

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int i,j,x,t,n,cnt;
    double a[15],b[15],c[15],ac[15],wa[15],ans,p;
    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++)
        {
            p=1;
            cnt=0;
            for(j=0;j<n;j++)
            {
                wa[j]=(1-a[j])*(1-b[j])*(1-c[j]);
                ac[j]=1-wa[j];
                if(i&(1<<j))
                {
                    p=p*ac[j];
                    cnt++;
                }
                else p=p*wa[j];

            }
            if(cnt==x)
                ans=ans+p;
        }
        printf("%.4lf\n",ans);
    }
    return 0;
}

简单的二进制枚举
核心思想:利用二进制的1,和0代表选择与不选择。将所有情况罗列开,并一位一位与各种情况进行对比,例如:


for(i=0;i<(1<<n);i++)//n是指集合中的元素的个数,(1<<n)==2^n指的是总共的情况数目
    {
        for(j=0;j<n;j++)//j代表的是每种元素对应的下角标
        {
            if(i&(1<<j))//                !!!!!代表选择(重大修改)!!!!!
            {
                
            }
            else(i&(1<<j)==0)//代表不选择;
        }
        if(     )//加入题目所给出的条件;
        {
            
        }

}

三、用异或比较不同(计算机中异或的操作是对于整型的操作,double不可以)

1.比较数的异或。

//此题是找出所有数中数字只出现一次的数
#include <bits/stdc++.h>
 
using namespace std;
 
int main()
{
    ios::sync_with_stdio(0);
    int n;
    while(cin >> n)            //共有n个数
    {
        long long ans=0;
        int x;                //x是要输入的数
        for(int i=1;i<=n;i++)
        {
            cin >> x;
            ans=ans^x;        //A^A=0,0^A=A,并且异或具有交换律
        }
        cout << ans << endl;
    }
    return 0;

}

2.比较字符串的异或

例题:NEFU teacher Li


#include<bits/stdc++.h>
using namespace std;
int n, tot=0;
string start, follow;
int main()
{
	while(cin>>n)
	{
		cin>>start;
		for(int i=1; i<n*2-1; i++)
		{
			cin>>follow;
			for(int j=0; j<max(start.size(), follow.size()); j++)
				start[j] ^= follow[j];
		}
		cout<<"Scenario #"<<++tot<<endl<<start<<endl<<endl;
	}
	return 0;

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!