二进制

题目

锐锐有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40。锐锐现在有n个想要得到的物品,每个物品的体积分别是a1,a2……an。锐锐可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,锐锐就可以得到这些物品。现在的问题是,锐锐有多少种不同的选择物品的方式。因为锐锐很忙,你可以帮助他计算一下吗?

输入

输入的第一行是正整数n (1 <= n <= 20),表示不同的物品的数目。接下来的n行,每行有一个1到40之间的正整数,分别给出a1,a2……an的值。

输出

输出不同的选择物品的方式的数目。

代码

#include<iostream>
using namespace std;

int a[22];
int cnt;

int main(){
	int n; cin >> n;
	for(int i = 0; i < n; i++)cin >> a[i];
	for(int i = 0; i < (1 << n); i++){//从 000..00 ~ 111...11
		int sum = 0;
		for(int j = 0; j < n; j++){//位数
			if(i & (1 << j)){//每一位分别与1做与运算,该位为1则返回true
				sum += a[j];
			}
		}
		if(sum == 40) cnt++;
	}	
	cout << cnt << '\n';
	return 0;
}

题目

给定一个二进制数组 nums ( 索引从0开始 )。

我们将xi 定义为其二进制表示形式为子数组 nums[0..i] (从最高有效位到最低有效位)。

例如,如果 nums =[1,0,1] ,那么 x0 = 1, x1 = 2, 和 x2 = 5。
返回布尔值列表 answer,只有当 xi 可以被 5 整除时,答案 answer[i] 为 true,否则为 false。

示例 1:

输入:nums = [0,1,1]
输出:[true,false,false]
解释:
输入数字为 0, 01, 011;也就是十进制中的 0, 1, 3 。只有第一个数可以被 5 整除,因此 answer[0] 为 true 。

代码

每一次都要进行左移,当前的数组数目为1则数的最后一位为1,为0则0
x = x<<1 | ve[i]
x = x*2 + ve[i]

题目

有一个正方形,顶点分别为(0,0),(0,2𝑁),(2𝑁,2𝑁),(2𝑁,0)。有一个点起始位于( 2^(𝑁-1), 2^(𝑁-1) ),四个顶点都可以对他进行吸引,使其坐标变为顶点和自身的中点坐标。题目保证所给数据一定有解,问至少多少次操作可以达到目标坐标(x ,y)?

输入

N,x, y

样例

4 3 1
3

思路

不妨设N为4,则起始坐标为(8, 8),横坐标的二进制表示为1000。可以对其进行操作(8+16)/2或者8/2,即是1000可以变为1100和0100。再进行一次操作则可以得到0110、1110、1010、0010,可以发现通过二进制操作可以得到任何一个数,则只需要关注原坐标的最后一位1和目标坐标的最后一位1,计算其差值即可。

代码

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

int main ()
{
    int n, x, y; cin >> n >> x >> y;
    int k = __builtin_ctz(x);
    n--;
    cout << n-k << '\n';
    return 0;
}
posted @ 2022-07-04 16:08  每日一题,医生远离  阅读(75)  评论(0)    收藏  举报