题解:ABC269C - Submask
·题目
链接地址:C - Submask (atcoder.jp)。
·难度
算法难度:普及
思维难度:入门
调码难度:普及
综合评价:中等
·算法
深度优先搜索(dfs)+二分查找
·思路
如果暴力枚举1~n中间每一个数判断行不行会超时,题目中给定n的二进制中最多有15个‘1’,通过数感我们发现这题的时间代价可能是215,仔细一想,可以设计一个dfs(d),表示从后往前考虑到n二进制中的倒数第d位,如果这一位本身是1可以有两个分叉,分别是将这一位变成0在递归前一位以及直接递归前一位,如果本身是0就只能直接递归前一位。
·细节
判断t的第d位是否为1:n>>(d-1))%2==1。
将t的第d位由1变成0:t-=1LL<<(d-1)。
将t的第d位由0变成1:t+=1LL<<(d-1)。
以哪一位作为递归入口(或者说n的二进制有几位):二分位数。
·代码
#include<bits/stdc++.h>
using namespace std;
long long l=0,m=0,n=0,t=0;
inline void dfs(int d);
int main(){
scanf("%lld",&n);
t=n;
int l=0,r=62;
while(l+1<r){
int mid=(l+r)/2;
if((1LL<<(mid-1))>n){
r=mid;
}else{
l=mid;
}
}
dfs(l);
return 0;
}
inline void dfs(int d){
if(d==0){
printf("%lld\n",t);
return;
}
if((n>>(d-1))%2==1){
t-=1LL<<(d-1);
dfs(d-1);
t+=1LL<<(d-1);
}
dfs(d-1);
}
·注意
每次<<操作都要用1LL。
二分时边界为0至62。
t要回溯。