习题: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;
}
posted @ 2020-08-24 16:37  loney_s  阅读(138)  评论(0)    收藏  举报