二进制枚举的一些思考和例题

二进制枚举

固定模板

for (int i=0;i<(1<

这样就把所有数遍历了一遍,用1<<去和i与就可以去选其中的某几个数
最后去应用这个方法解决一些问题
我觉得之所以用二进制思想去解决问题是因为二进制表示的一些巧妙的地方,这得慢慢
结合题目去悟

前提是得先学会二进制的一些基本运算法则

算数位运算:
1、与(&):
对于指定的两个数A=60(0011 1100)
B=13(0000 1101)
执行一下操作 A&B=12(0000 1100)
就是对二进制每一位进行了一次与操作,同为1,结果为1,否则为0
其实说白了就是只要有0就是0;
2、或(|):
对于指定的两个数A=60(0011 1100)
B=13(0000 1101)
执行一下操作 A|B=61(0011 1101)
就是对二进制每一位进行了一次或操作,同为0,结果为0,否则为1
说白了就是有1就为1;
关于与和或其实可以类比&& ||
3、非 按位取反(~):
对于指定的一个数A=60(0011 1100)
执行以下操作 ~A=195(1100 0011)
就是对二进制每一位进行了一次取反操作,若二进制数位0,则变成1,否则变成0.
4、异或运算
a,b值不同为1(就是两个数一个1 一个0) 相同时为0;
在c/c++中异或用^符号表示;
就是两个二进制数相加后的结果舍去进位

***任何数合0异或都是本身,对于异或一个非常重要的性质,对于一个值异或同一个值两次,则结果还是原值。

移位操作

移位操作有两种左移与右移:
1、左移<<
例如:A=5(0101)
如果向左移动一位即A<<1结果为1010,十进制的10。二进制中的左移就是乘二操作,在c/c++中左移运算速度比乘二速度要快。
其实就是往后面加多少个0
2、右移>>
例如:A=5(0101)
如果向右移动一位即A>>1结果为0010,十进制的2。二进制中的左移就是除二操作(舍去小数)。

例题

NEFU_OJ 1172

#include 

using namespace std;

int main()
{
    int n,a=0,x;
    while(cin>>n)
    {
        a=0;
        for(int i=0;i<n;i++)

            {
            cin>>x;
            a=a^x;}
        cout<<a<<endl;
    }
    return 0;
}

NEFU_OJ 1205

#include 

using namespace std;

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

    }if(flag==0)
            cout<<"No"<<endl;}
    return 0;
}

NEFU_OJ 1505

#include 
using namespace std;
int main()
{
    int t,tmp,ans,k1,k2,i,j;
    cin>>t;
    ans=0;
    for(i=0;i<(1<<15);i++)
    {
        tmp=t;
        k1=k2=0;
        for(j=0;j<15;j++)
        {
            if(i&(1<<j))
            {tmp=tmp*2;k1++;}
            else
            {
                tmp--;k2++;
                if(tmp==0) break;
            }
        }
        if(k1==5&&k2==10&&tmp==0)ans++;
    }
    printf("%d\n",ans);
    return 0;
}

NEFU_OJ 1518

#include 

using namespace std;
int a[20],ans,sum;
int main()
{
    int n,p;
    while(cin>>n>>p)
    {

        for(int i=0;i<n;i++)
            cin>>a[i];
        ans=0;
        for(int i=0; i<(1<<n); i++)
        {
             sum=0;
            for(int j=0; j<n; j++)
            {

                if(i&(1<<j))

                    sum+=a[j];

            }
            if(sum==p)
                ans++;
        }
        cout<<ans<<endl;
    }

    return 0;
}

NEFU_OJ 1641

在这里插入代码片

NEFU_OJ 1285

#include 

using namespace std;
double a[15],b[15],c[15],ac[15],no[15],ans,p,x,cnt;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=0;i<n;i++)
        cin>>a[i];
        for(int i=0;i<n;i++)
        cin>>b[i];
        for(int i=0;i<n;i++)
        cin>>c[i];
        cin>>x;
        ans=0;
        for(int i=0;i<(1<<n);i++)
        {
            p=1;cnt=0;
            for(int j=0;j<n;j++)
            {
                no[j]=(1-a[j])*(1-b[j])*(1-c[j]);
                ac[j]=1-no[j];
                if(i&(1<<j))
            {
                p=p*ac[j];
                cnt++;
            }
            else
                p=p*no[j];
            }
            if(cnt==x)
            ans=ans+p;
        }
    printf("%.4lf\n",ans);
    }
    return 0;
}

你可能感兴趣的:(大一寒假)