2023河南萌新联赛第(四)场:河南大学-B 序列的与和

2023河南萌新联赛第(四)场:河南大学-B 序列的与和

传送带

题目描述

WY是一个序列大师,他喜欢研究一些和序列相关的操作。时间长了,WY对某一些特定的序列产生了感情,换句话说,WY喜欢和这些特定的序列打交道。比如说WY最近就迷上了这样一类序列:

  • 我们规定序列的与和定义为序列中所有元素按位与得到的结果。

  • 如序列 [1,2,3] :其与和结果为1&2&3=0.

  • 若一个序列与和的结果,其二进制表示形式下包含 k 个 1 ,WY则会认为这是他喜欢的序列

现在WY的手里有一个序列了,他想知道,这个的序列的非空子序列中有多少个他喜欢的序列。由于WY已经非常熟悉这类序列了,所以他想考考你,看看你是否能解决这个问题。

子序列定义为:从原序列中去除几个(可以为零个)元素后得到的序列。

( 1 ≤ n ≤ 20 ) ( 0 ≤ k ≤ 20 ) ( 0 ≤ a i ≤ 2 64 − 1 ) (1 \le n \le 20 )(0 \le k \le 20 )(0 \le a_i \le 2^{64}-1 ) (1n20)(0k20)(0ai2641)

思路

首先它需要考虑所有的子序列 (至少含有一个数) 而n的范围只有20所以我们可以用二进制01表示是否取。复杂度也只有 O ( 2 n ∗ n ) O(2^n*n) O(2nn) 只需要将外层的循环中判断该位是否进子序列再与和运算即可
(说白了就是暴力)

上代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long 
int n,k;
ll a[25];
int sum=0;
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);	
    int kp=(1<<n);//每一个数是否取
    for(int i=1;i<kp;i++)//不考虑空串所以i从1开始
    {
        ll l,f=0;
        for(int j=1;j<=n;j++)
        {
            if((i>>(j-1))&1)//判断第j个数是否进此时的子序列
            {
                if(!f) {l=a[j];f=1;}
                else l&=a[j];
            }
        }
        int cnt=0;
        while(l) {
            l-=(l&-l);//删除01中最后一个1
            cnt++;//统计1的个数
        }
        if(cnt==k)
        {
            sum++;
        }
    }
    cout<<sum;
        
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值