题目链接
初始时,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。
输出格式
一个整数,表示所需付出的最小总代价。
数据范围
前 3 个测试点满足 。
所有测试点满足 。
输入样例1:
5
输出样例1:
2
输入样例2:
8
输出样例2:
1
解题思路
观察题目,题目很长,不要慌。我们由题可以得出,我们要将 n 最后变成 0。可以发现,就是求 n的二进制数中 1 的个数。n 可以由 0 向右边加若干个 0 或 1得到。乘二免费,则 n的二进制下 1 的位数为答案。
AC代码
#include<iostream>
using namespace std;
void change(int x,int num)
{
if(x==1)
{
cout<<1;
return;
}
int arr[100],len=0;
while(num!=0)
{
arr[len]=num%x;
len++;
num/=x;
}
int cnt=0;
for(int i=len-1;i>=0;i--)
{
if(arr[i]==1) cnt++;
}
cout<<cnt<<endl;
}
int main()
{
int x;
cin>>x;
change(2,x);
return 0;
}