输入一个无符号整数,用最少的步骤将该数变为1

输入一个无符号整数n,用最少的步骤将该数变为1,当n为偶数时可以采取的步骤是除2的形式,当n为奇数的时候可以采取加1或者减1的操作。

#include <math.h>
#include <iostream>

using namespace std;

int min(int a, int b) {
	if (a < b)
		return a;
	return b;
}

int get_pow(uint num) {
	if (num <= 1)
		return 0;
	int power = 0;
	while (0 == (num % 2)) {
		power++;
		num /= 2;
	}
	return power;
}

int get_step(uint num) {
	if (1 >= num)
		return 1;
	int step = 0;
	while (num > 1) {
		if (0 == (num % 2)) {
			step++;
			num /= 2;
		} else {
			int plus_pow = get_pow(num + 1);
			printf("num=%d,  plus_pow=%d\n", num, plus_pow);
			int minus_pow = get_pow(num - 1);
			printf("num=%d, minus_pow=%d\n", num, minus_pow);
			if (1 == plus_pow && 1 == minus_pow) {
				step += 1 + min(get_step(num - 1), get_step(num + 1));
				return step;
			} else if (plus_pow > minus_pow) {
				step += 1 + plus_pow;
				num = (num + 1) / ((int)pow(2.0, plus_pow));
			} else if (plus_pow < minus_pow) {
				step += 1 + minus_pow;
				num = (num - 1) / ((int)pow(2.0, minus_pow));
			}
		}
		if (3 == num) {
			step += 2;
			num = 1;
		}
	}
	if (0 == num)
		step += 1;
	return step;
}

int main(int argc, char* argv[]) {
	int num = 0;
	cin >> num;
	int step = get_step(num);
	cout << "step:" << step << endl;
	return 0;
}
时间: 2024-10-25 05:36:42

输入一个无符号整数,用最少的步骤将该数变为1的相关文章

C语言输入一个2-5位数,去除首位后剩的数!

#include <stdio.h>int main(){  int i;  do{   printf("请输入一个2-5位的数:");   scanf("%d",&i);   if(i>9&&i<=99)   printf("去掉首位后的余数为:%d\n",i%10);     else if(i>99&&i<=999)   printf("去掉首位后的余数为

小南刚学了二进制,他想知道一个数的二进制表示中有多少个1,你能帮他写一个程序来完成这个任务吗? 输入 第一行输入一个整数N,表示测试数据的组数(1&lt;N&lt;1000) 每组测试数据只有一行,是一个整数M(

#include<stdio.h> int main() { int n; int m; int i; int num=0; int a[32]; scanf("%d",&n); while(n--) { scanf("%d",&m); i=-1; while(m!=0) { i++; a[i]=m%2; m=m/2; } num=0; for(;i>-1;i--) { //    printf("%d",a[i

统计一个无符号整数的二进制表示中1的个数

#include <stdio.h>int countbit(unsigned int x); int main(void) { int x,n; printf("请输入一个无符号整数:\n"); scanf("%d",&n); x=countbit(n); printf("%d\n",x); } int countbit(unsigned int x) { unsigned int c=0; while(x>0) {

问对于一个给定的n,怎样才能用最少的步骤将它变到1

如果n为偶数,则将它除以2,如果n为奇数,则将它加1或者减1.问对于一个给定的n,怎样才能用最少的步骤将它变到1.例如:n= 61n-- 60n/2 30n/2 15n++ 16n/2 8n/2 4n/2 2n/2 1 算法设计:首先想到的是递规算法,不过细想一下我们可以动态规划:设a(i)为整数i用最少步骤变成1的解,设n=i+1 那么我们考虑a(n),如果n为偶数,那么a(n) = a(n/2) +1; 如果为奇数,那么a(n) = Min(a( (n+1)/2+2 ),   a((n-1)

输入一个整形数组(可能有正数和负数),求数组中连续子数组(最少有一个元素)的最大和。要求时间复杂度为O(n)(解决)

输入一个整形数组(可能有正数和负数),求数组中连续子数组(最少有一个元素)的最大和.要求时间复杂度为O(n). 输入描述: [重要]第一行为数组的长度N(N>=1) 接下来N行,每行一个数,代表数组的N个元素 输出描述: 最大和的结果 输入例子1: 8 1 -2 3 10 -4 7 2 -5 输出例子1: 18 思路:对输入的数组进行计算, import java.util.Scanner; public class Main { public static void main(String[]

Linux下别名alias设置(输入一个别名即可打印日志)

在Linux环境下,经常需要查看后台web日志,每次都要cd.很麻烦. 查看日志的时候,能否不用这么多cd呢?答案是能.方法如下: 步骤1:   vi  .profile 步骤2:在文件末尾增加别名showLog alias showLog='tail -100f  /pboss/iom/domain/iom/log.log' 保存文件.profile 步骤3:linux下,输入showLog,即可显示日志信息 总结:到此为止,大功告成.勉励自己继续积累吧 Linux下别名alias设置(输入一

(转)当你输入一个网址,实际会发生什么?

作为一个软件开发者,你一定会对网络应用如何工作有一个完整的层次化的认知,同样这里也包括这些应用所用到的技术:像浏览器,HTTP,HTML,网络服务器,需求处理等等. 简单来说有以下步骤:1. 查找域名对应的IP地址.这一步会依次查找浏览器缓存,系统缓存,路由器缓存,ISP DNS缓存,根域名服务器.2. 向IP对应的服务器发送请求.3. 服务器响应请求,发回网页内容.4. 浏览器解析网页内容.当然,由于网页可能有重定向,或者嵌入了图片,AJAX,其它子网页等等,这4个步骤可能反复进行多次才能将最

输入一个整数,判断其是否是2^n,是就输出这个数,不是就输出和它最接近的为2^n的那个整数。

输入一个整数,判断其是否是2^n,若是,输出这 //个数,若不是,输出和它最接近的为2^n的那个整数. 附加源代码1: #include<stdio.h> #include<stdlib.h> #include<math.h> int main() { int input;//键盘输入一个整数input int i,j;//i,j待会儿存放input与左边和右边的为2^n的差值 int m,n;//保存左边,右边的与inout最接近的2^n printf("请

C语言——输入一个字符串,将连续数字字符转换为数字

输入一个字符串,内有数字和非数字字符,例如: A123cdf 456.78cpc876.9er 849.1 将其中连续的数字作为一个实数,依次存放到一数组a中.例如123存放在a[0],456.78存放在a[2],依次类推,统计共有多少个数,并输出这些数. #include <stdio.h> #include <string.h> #include <math.h> #define N 50 int Number(char str[],float num[]); in