• Codeforces Round #460 (Div. 2) B Perfect Number(二分+数位dp)


    B. Perfect Number
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    We consider a positive integer perfect, if and only if the sum of its digits is exactly 1010. Given a positive integer kk, your task is to find the kk-th smallest perfect positive integer.

    Input

    A single line with a positive integer kk (1k100001≤k≤10000).

    Output

    A single number, denoting the kk-th smallest perfect integer.

    Examples
    input
    Copy
    1
    output
    Copy
    19
    input
    Copy
    2
    output
    Copy
    28
    Note

    The first perfect integer is 1919 and the second one is 2828.

    题意:求出第k个各位数和为10的数

    题解:本题k的范围比较小,所以暴力可以解决

    但是当范围大的时候,就要用数位dp了

    数位dp记录的是小于某个数的符合条件的数有多少个

    用二分去枚举

    代码:

    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<stdio.h>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long long ll;
    typedef pair<int,int> PII;
    #define mod 1000000007
    #define pb push_back
    #define mp make_pair
    #define all(x) (x).begin(),(x).end()
    #define fi first
    #define se second
    //head
    int k;
    ll a[10005];
    bool check(ll x)
    {
        ll ans=0;
        while(x){
           ans+=x%10;
           x/=10;
        }
        return ans==10;
    }
    int main()
    {
        scanf("%d",&k);
        int p=0;
       for(int i=0;i<11000006;i++)
       {
           if(check(i))
              {
                  a[++p]=i;
              }
       }
       printf("%lld
    ",a[k]);
        return 0;
    }
    枚举 873 ms 300 KB
    #include<bits/stdc++.h>
    using namespace std;
    int k;
    bool check(int x)
    {
        int ans=0;
        while(x){
           ans+=x%10;
           x/=10;
        }
        return ans==10;
    }
    int main()
    {
        scanf("%d",&k);
        int p=0;
       for(int i=0;i<11000006;i++)
       {
           if(check(i))
              {
                  p++;
                  if(p==k)
                  {
                        printf("%d
    ",i);
                  }
              }
       }
    
        return 0;
    }
    枚举 140 ms 0 KB
     
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<stdio.h>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long long ll;
    typedef pair<int,int> PII;
    #define mod 1000000007
    #define INF 0x3f3f3f3f
    #define pb push_back
    #define mp make_pair
    #define all(x) (x).begin(),(x).end()
    #define fi first
    #define se second
    //head
    int k;
    int bit[11];
    int dp[20][11];//表示到第i位,数位和为j的个数
    int dfs(int pos,int sum,bool limit)
    {
        if(pos==-1) return sum==10;
        if(sum>10)return 0;
        if(!limit&&dp[pos][sum]!=-1)return dp[pos][sum];
        int ans=0;
        int up=limit?bit[pos]:9;
        for(int i=0;i<=up;i++)
        {
            ans+=dfs(pos-1,sum+i,limit&&(i==up));
        }
        if(!limit) dp[pos][sum]=ans;
        return ans;
    }
    int calc(int x)
    {
        int len=0;
        while(x)
        {
            bit[len++]=x%10;
            x/=10;
        }
        return dfs(len-1,0,true);
    }
    int main()
    {
        memset(dp,-1,sizeof(dp));
        while(~scanf("%d",&k))
        {
            int lb=0,ub=INF;
            int ans=0;
            while(ub-lb>1){
                int mid=(lb+ub)/2;
                if(calc(mid)<k) lb=mid;
                else ans=mid,ub=mid;
            }
            printf("%d
    ",ans);
        }
    
        return 0;
    }
    二分+数位dp 31 ms 0 KB
  • 相关阅读:
    移动端兼容
    三点优化
    面向对象(一)
    BootCDN和npm
    分页逻辑
    多物体运动框架
    兼容样式
    省略
    行内元素在水平和垂直排列的时候会有间距
    [Swift]LeetCode1053.交换一次的先前排列 | Previous Permutation With One Swap
  • 原文地址:https://www.cnblogs.com/zhgyki/p/9769981.html
Copyright © 2020-2023  润新知