• AcWing310 启示录(数位dp)


    这道题因为要求的是第k大的魔鬼数

    所以我们可以采用二分的方法,用k-1来二分,这样就可以找到最左边的>=k的,也就是第k大

    之后是数位dp,题目要求的是666,因此我们考虑用两位表示前一位填p1,前前位填p2。剩下的还要保存在这个数之前是否已经存在魔鬼数,这便与边界判断数是否成立,还有一维是老套路,看是否是最大的

    #include<iostream>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef long long ll;
    vector<int> num;
    int f[20][2][2][2][2];
    int k;
    int dfs(int cur,int p2,int p1,int m,int flag){
        if(cur==(int)num.size())
        return m==1;
        if(f[cur][p2][p1][m][flag]!=-1)
        return f[cur][p2][p1][m][flag];
        int v=9;
        if(flag)
        v=num[cur];
        int i;
        long long ans=0;
        for(i=0;i<=v;i++){
            ans+=dfs(cur+1,p1,i==6,m||(p1&&p2&&(i==6)),flag&&(i==v));
        }
        return f[cur][p2][p1][m][flag]=ans;
    }
    int check(ll n){
        num.clear();
        while(n){
            num.push_back(n%10);
            n/=10;
        }
        reverse(num.begin(),num.end());
        memset(f,-1,sizeof f);
        int ans=dfs(0,0,0,0,1);
        return ans<=k;
    }
    int main(){
        int t;
        cin>>t;
        while(t--){
            cin>>k;
            k--;
            ll l=0,r=1e10;
            while(l<r){
                ll mid=(l+r)>>1;
                if(check(mid))
                l=mid+1;
                else
                r=mid;
            }
            cout<<l<<endl;
        }
    }
    View Code
  • 相关阅读:
    C语言中可变函数参数变量的实现
    Oracle电话面试
    JS和C#方法相互调用
    asp.net 页面从初始化到卸载事件顺序
    解决.NET CF 3.5 Bitmap(Stream)未处理异常问题
    sql2008新增时间类数据类型学习
    c#和Javascript操作同一json对象
    被研究生了
    分形
    跑钱
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12697482.html
Copyright © 2020-2023  润新知