【五一创作】AcWing——凑数(二进制中1的个数)

简介: 【五一创作】AcWing——凑数(二进制中1的个数)

4941. 凑数 - AcWing题库


1、题目

初始时,n=0。


每一轮操作都要依次完成两个步骤:


第一步,任选一个非负整数 a,将 n增加 a,这一步所需付出的代价为 a。

第二步,将 n 乘以 2,这一步无需付出任何代价。

你可以不断重复上述操作。


给定一个整数 x,你的任务是使 n 在某一步操作后(不一定是某一轮结束后)恰好等于 x 且付出的总代价尽可能少。


请你计算,为了完成任务所需付出的最小总代价。


例如,如果 x=5,则最佳操作方案为:


第 1 轮操作中,第一步,将 n 增加 1(付出代价 1),使得 n 变为 1,第二步,将 n 乘以 2,使得 n 变为 2。

第 2 轮操作中,第一步,将 n 增加 0(付出代价 0),则 n 仍然为 2,第二步,将 n 乘以 2,使得 n 变为 4。

第 3 轮操作中,第一步,将 n 增加 1(付出代价 1),使得 n 变为 5。此时 n 等于 x 成立,任务完成。

付出的最小总代价为 2。

再例如,如果 x=8,则最佳操作方案为:


第 1 轮操作中,第一步,将 n 增加 1(付出代价 1),使得 n 变为 1,第二步,将 n 乘以 2,使得 n 变为 2。

第 2 轮操作中,第一步,将 n 增加 0(付出代价 0),则 n 仍然为 2,第二步,将 n 乘以 2,使得 n 变为 4。

第 3 轮操作中,第一步,将 n 增加 0(付出代价 0),则 n仍然为 4,第二步,将 n 乘以 2,使得 n 变为 8。此时 n等于 x 成立,任务完成。

付出的最小总代价为 1。

输入格式


一个整数 x。


输出格式


一个整数,表示所需付出的最小总代价。


数据范围


前 3 个测试点满足 1≤x≤10。

所有测试点满足 1≤x≤10⁹。

输入样例1:

5

输出样例1:

2

输入样例2:

8

输出样例2:

1

2、题目解读

看完题目我们知道了加法需要付出代价,乘法不需要付出代价,也就是说我们应该尽量使用乘法去使n变成x。

我们 n(0)->x 可能困难,可是 x->n(0) 就简单了,这时乘法就变成了除法(除以2),而思路就出来了我们应该 使用减法(最小代价就是减1)将x保持成偶数,再x除以二,不断重复上面过程就可以求解出答案。仔细推敲可以发现,就是求 n二进制中 1 的个数。那么这样我们也随便复习一下怎样求二进制中 1 的个数吧!

3、代码

Ⅰ、正常求解

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
         Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int i=0;
        while (n!=0){
            if (n%2==0)
                n/=2;
            else {
                n-=1;
                i++;
            }
        }
        System.out.println(i);
    }
}

Ⅱ、使用Integer.bitCount()方法:这是一种内置于Java的方法,通过调用该方法即可计算一个整数中1的个数。

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        System.out.println(Integer.bitCount(n));
    }
}

Ⅲ、可以使用位运算符和循环来计算一个二进制数中1的个数。算法基本思路是将目标数每次右移一位,并且与1进行与运算,如果结果为1,则说明当前位是1,否则为0。循环直到目标数变为0。

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
       Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int count = 0;
        while (n > 0) {
            if ((n & 1) == 1) {
                count++;
            }
            n >>= 1;
        }
        System.out.println(count);
    }
}

Ⅳ、Brian Kernighan算法:该算法是一种优化的常规方法,它的基本思路是利用n&(n-1)可以将n最右边的1变成0的特性,循环直到目标数变为0。

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
       Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int count = 0;
        while (n > 0) {
            n &= (n - 1);
            count++;
        }
        System.out.println(count);
    }
}


目录
相关文章
|
17天前
|
存储 算法
力扣经典150题第四十四题:快乐数
力扣经典150题第四十四题:快乐数
7 0
|
2月前
【一刷《剑指Offer》】面试题 10:二进制中 1 的个数
【一刷《剑指Offer》】面试题 10:二进制中 1 的个数
|
2月前
【一刷《剑指Offer》】面试题 12:打印 1 到最大的 n 位数
【一刷《剑指Offer》】面试题 12:打印 1 到最大的 n 位数
|
2月前
|
C语言
PTA 浙大版《C语言程序设计(第3版)》题目集 习题8-6 删除字符 (20分)
PTA 浙大版《C语言程序设计(第3版)》题目集 习题8-6 删除字符 (20分)
|
2月前
|
人工智能 算法 Java
截断数组(蓝桥杯每日一题)
截断数组(蓝桥杯每日一题)
27 0
|
8月前
|
算法 测试技术 容器
代码随想录算法训练营第四十二天 | LeetCode 1049. 最后一块石头的重量 II、494. 目标和、474. 一和零
代码随想录算法训练营第四十二天 | LeetCode 1049. 最后一块石头的重量 II、494. 目标和、474. 一和零
34 1
|
11月前
|
测试技术 C语言 C++
【浙江大学PAT真题练习乙级】1006 换个格式输出整数 (15分) 真题解析
【浙江大学PAT真题练习乙级】1006 换个格式输出整数 (15分) 真题解析
|
12月前
|
机器学习/深度学习 Cloud Native
【刷题日记】67. 二进制求和
本次刷题日记的第 15 篇,力扣题为:67. 二进制求和 ,简单
|
人工智能
【蓝桥杯集训·每日一题】AcWing 3956. 截断数组
文章目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 三、知识风暴 一维前缀和
51 0
|
人工智能 BI
【寒假每日一题】AcWing 4699. 如此编码
目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解
41 0