题目
初始有一个数n,每过一秒所有大于1的数x都会分裂成3部分:[x/2] , x%2 , [x/2]
问经过足够长的时间后,即所有的数都是0或1的时候,0的个数是多少
输入数据
一个正整数n,n<=1e12
输出数据
最终0的个数
样例输入
5
样例输出
2
样例说明
注意n要用long long存 样例解释: {5}-->{2,1,2}-->{1,0,1,1,1,0,1}
思路
递归的思路很直接,分裂前后的数处理方式都是一样的。分裂后是更小的同质的问题,完美符合递归的定义。
递归结束条件:
(1)分裂后得到1,返回0(返回值是0的个数,得到一个1,0的个数就是0)
(2)分裂后得到0,返回1(返回值是0的个数,得到一个0,0的个数就是1)
分裂后:
(1)对于[x/2],x减少的速度是,时间复杂度就是
,所以这题虽然是递归问题,但其实到递归尽头的速度很快。
因为分裂后有两个[x/2],所以返回值要乘2
(2)对于x%2,结果只可能1或0,直接到递归尽头了。
数学表达:
定义breakdown(int n):n完全分裂后产生的0的个数
递归终点:breakdown(1)=0,breakdown(0)=1
递归公式:breakdown(n)=2*breakdown(n/2)+breakdown(n%2) (n>=2)
代码
#include<iostream>
using namespace std;
long long int breakdown(long long int n)
{
if(n==0) return 1;
else if(n==1) return 0;
else return 2*breakdown(n/2)+ breakdown(n%2);
}
int main()
{
long long int n;
cin>>n;
cout<<breakdown(n)<<endl;
return 0;
}