习题:Random Task(数位DP)
题目
思路
很明显有单调性
之后就是一个数位dp的板子题目
\(dp_{i,j}\)前i位,还有j个1没有填
代码
#include<iostream>
#include<cstring>
using namespace std;
unsigned long long l=1,r=1e18,mid;
long long m,k;
long long len;
long long dp[105][105],limit[105];
void divide(long long val)
{
len=0;
while(val)
{
limit[len++]=(val&1);
val>>=1;
}
len--;
}
long long dfs(int pos,long long k,int lim)
{
if(k<0)
return 0;
if(pos==-1)
return k==0?1:0;
if(lim==0&&dp[pos][k]!=-1)
return dp[pos][k];
long long ret=0;
for(int i=0;i<=(lim?limit[pos]:1);i++)
ret=ret+dfs(pos-1,k-i,lim&&i==limit[pos]);
if(lim==0)
dp[pos][k]=ret;
return ret;
}
long long calc(long long val)
{
divide(val);
return dfs(len,k,1);
}
int main()
{
memset(dp,-1,sizeof(dp));
cin>>m>>k;
while(l+1<r)
{
mid=(l+r)>>1;
if(calc(mid*2)-calc(mid)>=m)
r=mid;
else
l=mid;
}
while(calc(l*2)-calc(l)!=m)
l++;
cout<<l;
return 0;
}