首页 > 其他分享 >20240318每日一题题解

20240318每日一题题解

时间:2024-03-18 15:26:21浏览次数:19  
标签:count 类数 int 题解 每日 20240318 ++ 二进制 个数

20240318每日一题题解

Problem

若将一个正整数化为二进制数,在此二进制数中,我们将数字 \(1\) 的个数多于数字 \(0\) 的个数的这类二进制数称为 \(A\) 类数,否则就称其为 \(B\) 类数。

例如:

\((13)_{10}=(1101)_2\),其中 \(1\) 的个数为 \(3\),\(0\) 的个数为 \(1\),则称此数为 \(A\) 类数;

\((10)_{10}=(1010)_2\),其中 \(1\) 的个数为 \(2\),\(0\) 的个数也为 \(2\),称此数为 \(B\) 类数;

\((24)_{10}=(11000)_2\),其中 \(1\) 的个数为 \(2\),\(0\) 的个数为 \(3\),则称此数为 \(B\) 类数;

程序要求:求出 1~n 之中(\(1 \le n \le 1000\)),全部 \(A,B\) 两类数的个数。

输入输出格式

输入 \(n\)。

输出一行,包含两个整数,分别是 \(A\) 类数和 \(B\)​ 类数的个数,中间用单个空格隔开。

输入输出样例

输入1

7

输出1

5 2

Solution

除法和取余

对于数字x,我们从低位开始考虑。

如果x除以2的余数是1,则说明x在二进制下的最低位是1

如果x除以2的余数是0,则说明x在二进制下的最低位是0

而将x除以2,就可以将x的最低位直接抹去

​ 例如:\((10)_{10}=(1010)_2\),10/2=5,\((5)_{10}=(101)_2\)​

只要x还有值,那么就判断x的最低位是0还是1,并且将x的最低位抹去

#include<iostream>
using namespace std;

int main()
{
	int n;
	cin>>n;
	int count_A=0,count_B=0; // 两个变量用来存放A类数和B类数的数量
	for(int i=1;i<=n;i++)
	{
		int x=i; // x为当前要判断的数
		int number0=0,number1=0; // 用两个变量统计 x 中的0和1的数量
		// 重点!使用除法和取余数来统计
		while(x) // 只要x还有值
		{
			if(x%2 == 1) number1++; // 使用取余数来得到x在二进制下最低位是0还是1
			else number0++;
			x/=2; // 使用除法来让x在二进制下的最低位抹去
		}
		
		if(number1>number0) count_A++; // 如果1比0多,则归为A类数
		else count_B++;
	}
	cout<<count_A<<" "<<count_B<<endl;
	return 0;
}

二进制位运算

c++对于整数二进制运算支持的非常好,下面介绍两种二进制运算符

  1. &(按位与):将两个操作数的二进制按位比较,仅当对应位都是1时,结果的这一位才为1。

    10011010011 & 00000011001 = 00000010001

  2. >>(右移位):将操作数的所有位向右移动指定的位数,低位直接抹去。

    10011010010 >> 2 = 100110100

可以用x&1来判断x的最低位是不是11 的二进制表示是 000...0001x&1就相当于只保留 x 的最低位。

有了以上的铺垫,我们就能很轻松的提取了。我们这需要每次把数和1进行按位且操作,这样就能提取出这个数的最后一位,然后在把这个数右移一位就行了。

#include<iostream>
using namespace std;

int main()
{
	int n;
	cin>>n;
	int count_A=0,count_B=0;//两个变量用来存放A类数和B类数的数量
	for(int i=1;i<=n;i++)
	{
		int x=i;//x为当前要判断的数
		int number0=0,number1=0;//用两个变量统计 x 中的0和1的数量
		//重点!
		while(x)//只要x还有值
		{
			if(x&1) number1++;//用二进制运算符&(二进制与)得到x在二进制下最低位是0还是1
			else number0++;
			x>>=1;//二进制右移运算符,让x在二进制下的最低位抹去
		}
		
		if(number1>number0) count_A++;//如果1比0多,则归为A类数
		else count_B++;
	}
	cout<<count_A<<" "<<count_B<<endl;
	return 0;
}

STL

c++中提供一种容器bitset,其有一个功能可以将十进制数字转成二进制数字,count()函数还可以统计其中的1的数量。

那么0的位数可以由二进制下的位数总数减去1的个数得到

二进制下的位数总数可用公式\(\lfloor\log_2x+1\rfloor\)得到

#include<iostream>
#include<bitset>//bitset的头文件
#include<cmath>//使用取以2为底的对数函数log2()需要包含cmath
using namespace std;

int main()
{
	int n;
	cin>>n;
	int count_A=0,count_B=0;//两个变量用来存放A类数和B类数的数量
	for(int i=1;i<=n;i++)
	{
		bitset<20>x(i);//定义一个最大长度为20的bitset,其十进制值是i
		int number1=x.count();//1的数量直接用count()函数统计
		int number0=floor(log2(i)+1)-number1;//0的数量是用二进制数的总位数减去1的数量
		//使用log2(i)下取整在加一,得到i在二进制下的总位数
		
		if(number1>number0) count_A++;//如果1比0多,则归为A类数
		else count_B++;
		
	}
	cout<<count_A<<" "<<count_B<<endl;
	return 0;
}

内置函数(不推荐)

在C++中,一些编译器(如GCC和Clang)提供了一些内置函数来执行一些常见的位操作,例如:

__builtin_popcount:计算整数在二进制下1的数量

__builtin_clz:计算整数在二进制下前导0的数量

而我们又知道,int整型是32位的,即共有320/1

所以,1的个数=__builtin_popcount

0的个数=32-前导零__builtin_clz-1的个数

#include<iostream>
using namespace std;

int main()
{
	int n;
	cin>>n;
	int count_A=0,count_B=0;//两个变量用来存放A类数和B类数的数量
	for(int i=1;i<=n;i++)
	{
		int number1=__builtin_popcount(i);
		int number0=32-__builtin_clz(i)-number1;
		if(number1>number0) count_A++;//如果1比0多,则归为A类数
		else count_B++;
		
	}
	cout<<count_A<<" "<<count_B<<endl;
	return 0;
}

标签:count,类数,int,题解,每日,20240318,++,二进制,个数
From: https://www.cnblogs.com/Vanilla-chan/p/18080459

相关文章

  • 20240317每日一题题解
    20240317每日一题题解ProblemSolution提供两种写法,分别用到了string类和c风格字符串。string类是标准库中提供的用于处理字符串的类,避免了传统的C语言中使用字符数组来处理字符串时需要考虑的空间分配、长度控制等问题。c风格字符串实际上就是一个字符数组char[],以字符'......
  • CF999D Equalize the Remainders 题解
    题意给定一个长度为\(n\)的序列和一个模数\(m\),记\(c_i\)表示\(\bmodm\)后的结果为\(i\)的数的个数。现在可以使每个数增加\(1\),请问最少要操作多少次才能使所有\(c_i=\frac{n}{m}\)。并输出最后的序列。First.如何最小化操作次数由于每次操作会使\(c_{a_i\bm......
  • AT_hhkb2020_e Lamps 题解
    \(\mathtt{TAG}\):计数、数学变量说明下文中\(k\)指整洁方块个数。First.如何计数?一个方案一个方案地数肯定是不现实的,不妨反过来想:每个方块在多少个方案中被照亮。Second.如何求多少个方案首先预处理出有多少位置可以将\(s_{i,j}\)照亮。记为\(x\)。这个很简单,不......
  • 怎么在电脑上记录每日事项,并在桌面上显示便签记事本?
    作为一名教师兼班主任,我每天的工作繁忙且多样。从早晨的课程准备,到课间的学生辅导,再到课后的作业批改和家长沟通,每一项工作都需要我细心且有条理地完成。在这样的工作节奏下,如何高效管理每日事项,确保不遗漏任何重要任务,成为了我必须面对的挑战。电脑桌面便签、记事本插件,正是我应......
  • CF933-Div3 大致思路+题解
    A-RudolfandtheTicket纯水题暴力枚举直接过$code$#include<bits/stdc++.h>#definefo(x,y,z)for(int(x)=(y);(x)<=(z);(x)++)#definefu(x,y,z)for(int(x)=(y);(x)>=(z);(x)--)inlineintqr(){ charch=getchar();intx=0,f=1; for(;ch<'0......
  • 【题解】A18535.来自领导的烦恼
    题目跳转思路:本题可以使用动态规划或递归的方式来实现,本质上是一道01背包的变型题。假设一共有\(n\)名员工,每一位员工的技能水平用\(a[i]\)表示。要使得两个部门的员工技能总和之差最小,意思就是尽可能地将一个部门的技能之和”凑“到\(\sum\limits_{i=1}^{n}a[i]\times\frac{1}......
  • 【题解】A18536.星光交错的律动
    题目跳转思路:这道题可能跟博弈论有一点关系,没有学习过博弈论做起来应该问题也不大。思考一个问题,先手必胜的前提是什么?有关更多的内容可以前往:浅谈有向无环图先手必胜的前提是,在任何一种局面下,先手都有至少一种操作可以使后手处于必败的局面。若先手进行任何操作后,后手都可以......
  • 【题解】A18537.我心中珍藏的游戏
    题目跳转思路:题目问最多可以获得的额外伤害,其实就是询问在这些技能中,如何怎样选取一个最优的发动技能顺序使得攻击加成最大。我们可以把每一个技能看作成一个图的顶点,把每一个攻击加成看作图的边,权制为\(Ei,j\)。由于\(Ei,j\)与\(Ej,i\)相等,则可以将这个图视为无向图。可以样样......
  • 【题解】P2627 [USACO11OPEN] Mowing the Lawn G
    【题解】P2627[USACO11OPEN]MowingtheLawnG题目跳转数据量比较大,暴力肯定是不行的。只能考虑用动态规划的方式来做。这道题有许多dp设计的思路,这里提供两个:方法一:普通状态设计定义\(dp[i][1/0]\)表示截止遍历到第\(i\)个元素时,选择第\(i\)个元素或不选第\(i\)个元素可以......
  • cfRound933div3-E题解
    E-RudolfandkBridges题意:选择的桥在连续的行中,每个桥的支架安装位置是可以不一样的.做法:赛时也感觉也感觉是dp,但是害怕dp,就选择了逃避.往贪心方向想,认为每次到了每个跳板都要跳到最远距离,实际上这样是不行的.很明显,可能存在近一点的点花费更少。实际上是dp,而且也不......