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\n",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\n",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\n",ans);
    }

    return 0;
}
二分+数位dp 31 ms 0 KB

 

 

posted @ 2018-10-10 23:47  better46  阅读(290)  评论(0编辑  收藏  举报