【算法】数位DP
【题解】动态规划
写了预处理函数却忘了调用是一种怎样的体验?
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int f[35][35]; void init() { f[0][0]=1; for(int i=1;i<=31;i++) { f[i][0]=1; for(int j=1;j<=i;j++)f[i][j]=f[i-1][j]+f[i-1][j-1]; } } int find(int x,int k) { int tot=0,ans=0; for(int i=31;i>0;i--) { if((1<<i)&x) { tot++; if(tot>k)break;//超过k就没有意义了 x^=(1<<i); } if((1<<(i-1))<=x)ans+=f[i-1][k-tot]; } if(tot+x==k)ans++;//判断x本身 return ans; } int calc(int l,int r,int k)//统计0...x内二进制表示含k个1的数的个数 { int s,now=0; for(s=0;now<k;s++)now+=find(r,s)-find(l-1,s); s--;now=k-now+find(r,s)-find(l-1,s); int left=l; while(l<r) { int mid=(int)(((long long)l+(long long)r)>>1);//int+int会范围爆炸 if(find(mid,s)-find(left-1,s)>=now)r=mid;else l=mid+1; } return l; } int main() { int TT,l,r,k; init(); scanf("%d",&TT); while(TT--) { scanf("%d%d%d",&l,&r,&k); if(r<=0) { if(r==0)r--,k--; l^=(1<<31),r^=(1<<31); printf("%d\n",(1<<31)|calc(l,r,k)); continue; } if(l==0)l++,k--; printf("%d\n",calc(l,r,k)); } return 0; }