题意:给定一个数n, 如果这个数大于1,把这个数拆分成3个数 成为一个序列,对于序列中大于1 的数 进行以上操作,直到序列中只有0和1,问区间【l,r】内有多少个1
n的数据范围不超过
2
50
2^{50}
250,int数据范围是
2
32
2^{32}
232
模拟二叉树中序遍历特征的做法
1125899906842623 1 100001 这个魔鬼样例,超出题目说的范围了,恰好
2
50
2^{50}
250
这张图片好看,节点内的数值是中序遍历的序号
#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#define int long long
using namespace std;
signed main(){
int n,l,r;
cin>>n>>l>>r;
if(n==0||n==1){
cout<<n;
return 0;
}
int cnt=log2(n)+1;
vector<int> v;
v.clear();
while(n){
v.push_back(n%2);
n>>=1;
}
reverse(v.begin(),v.end());
int res=0;
for(int i=l;i<=r;i++){
int ceng=log2(i&(-i))+1;
if(v[ceng-1]==1)res++;
}
cout<<res;
return 0;
}
好的,都过不去。。。 为什么我会突发奇想添油加醋 先搞个排序还撞对了,大佬们几年前的题解现在交上去都过不去那个魔鬼样例,可能是后面加强了数据(加了个超出数据范围的样例?)
#include <iostream>
#include <algorithm>
#include <math.h>
#include <map>
#define int long long
using namespace std;
signed main(){
int n,l,r;
cin>>n>>l>>r;
if(n==0||n==1){
cout<<n;
return 0;
}
int cnt=log2(n);
cnt=pow(2,cnt+1);
cnt/=2;
map<int,int> mp;
mp.clear();
while(cnt){
mp.insert({cnt,n%2});
cnt>>=1;
n>>=1;
}
int res=0;
for(int i=l;i<=r;i++){
int ceng=log2(i&(-i));
int x=pow(2,ceng);
if(mp[x]==1)res++;
}
cout<<res;
return 0;
}
参考思路
参考做法,要动手画二叉树 这位博主也是,转置了才能AC,why?
递归分治
8 下面有3层 ,x和自x以下共有4层,每层的数量呈等比数列 1+2+4+8 根据等比数列,2^n -1,首项为1,共有n项 可以计算出,最终序列的长度 或者直接len=1,len=len*2+1,n/=2;
递归自然就是在1~len范围内,还是可以构想一颗二叉树,递归的过程是 得到左右两颗子树,分别计算出左右两棵子树中的1的个数
#include <iostream>
#include <algorithm>
#include <math.h>
#define int long long
using namespace std;
int n,lx,rx;
int solve(int x,int l,int r){
if(r<lx||l>rx)return 0;
if(x<2){
if(l>=lx&&r<=rx)return x;
else return 0;
}
int half=(l+r)>>1;
return solve(x/2,l,half-1)+solve(x%2,half,half)+solve(x/2,half+1,r);
}
signed main(){
cin>>n>>lx>>rx;
if(n==0||n==1){
cout<<n;
return 0;
}
int x=n,len=1;
while(x!=1){
len=len*2+1;
x/=2;
}
cout<<solve(n,1,len);
return 0;
}
|