Codeforces Round #460 (Div.2) - B - Perfect Number (模拟)

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 10. Given a positive integer k, your task is to find the k-th smallest perfect positive integer.

Input

A single line with a positive integer k (1 ≤ k ≤ 10 000).

Output

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

Examples
input
1
output
19
input
2
output
28
Note

The first perfect integer is 19 and the second one is 28.


题意:

找到第k小的Perfect Number(每一位数的和为10)




可以利用 各位数和为10的数 + 9 和依然为 10  



从前往后推出每一位是什么数字


具体步骤:

先判断第k小完美数的位数,然后判断该位数为几,然后还有些细节问题,有点像是二分求第k大的感觉





第二列的9 表示一个两位数的和为10 的共有9


位数为 i(i >= 3) 的完美数的种数 = 位数为i-1 的各位数和为 k 的种数之和(k = 9,8,..,2,1) 

 因为是完美数所以 i 位数第 i 位不为 0,其余位之和 + 第 i 位 (1~9) = 10 其余位数之和可以为(9~1)

位数为 i(i >= 3)的各位数和为k(10 > k > 0) 的种数 = 位数为 i-1 的各位数和为 j 的种数之和 (k > j >= 0)

因为不是完美数所以 i 位数第 i 位可以为 0,其余位之和 (k~0) + 第 i 位 (0~k) = k



#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int n,m = 10;
int a[10][15];
int main()
{
    a[2][10] = 9;
    for(int i=0;i<=9;i++) a[2][i] = i + 1;
    for(int i=3;i<=8;i++) {
        for(int k=9;k>=1;k--){
            a[i][10] += a[i-1][k];
        }
        for(int j=9;j>=0;j--){
            for(int k=j;k>=0;k--){
                a[i][j] += a[i-1][k];
            }
        }
    }
    scanf("%d",&n);
    string ans = "";
    for(int i=2;i<=8;i++){
        //先找到位数
        if(n<=a[i][10]){
            //位数剩下两位就要直接来
            if(i==2){
                ans += ('0' + n);
                ans += ('0' + 10 - n);
                break;
            }
            for(int k=9;k>=1;k--){
                //第一位是9到1,其余位是9到0所以第一位要拿出来考虑
                if(a[i-1][k]>=n){
                    m = k;
                    ans += ('0' + 10 - k);
                    break;
                }
                n -= a[i-1][k];
            }
            if(i==3){
                for(int k=m;k>=0;k--){
                    if(a[2][k]>=n){
                        ans += ('0' + n - 1);
                        ans += ('0' + k - n + 1);
                        break;
                    }
                }
            }
            for(int j=i-2;j>=2;j--){
                for(int k=m;k>=0;k--){
                    if(a[j][k]>=n){
                        ans += ('0' + m - k);
                        m = k;
                        if(j==2){
                            ans += ('0' + n - 1);
                            ans += ('0' + k - n + 1);
                            break;
                        }
                        break;
                    }
                    n -= a[j][k];
                }
            }
            break;
        }
        n -= a[i][10];
    }
    cout<<ans<<endl;
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值