D. Expression Evaluation Error

D. Expression Evaluation Error

题目

D. Expression Evaluation Error

题意

给你一个十进制数s,n,要求你把s拆成用n个10进制数的和,再把这n个十进制数看成11进制,让这n个11进制数的和的11进制尽管可能大。

分析

首先n个数按11进制求和一定小于等于按10进制求和,因为11进制是逢11进1,10进制逢10进1,所以11进制相比10进制每次进位都要亏损1个1。所以为了让答案尽可能的大,我们可以尽量在做加法的时候不让它进位,即使需要进位也要让它在低位进位,这样损耗更小。

所以我没可以从左到右考虑s的每一位,把高位拆出一个1出来当作一个数,这样就能尽可能多的构造出需要的n个数并且拆出来的几个数相加是不会在当前位进位(当且仅当高位减去1后剩下的这个数不小于还需构造的数个数才)

那么当不满足上面的条件时,不得不进位呢?
比如 s = 11 , n = 3 s = 11, n = 3 s=11,n=3
按上面构造方法 把高位拆出一个1出来当作一个数得到10,那么,剩下的数就是 11 − 10 = 1 11 - 10 = 1 11−10=1但是可以看到剩下的数 1 < 3 − 1 1 < 3 - 1 1<3−1 也就是剩下的低位1 不够继续构造2个数了,所以这一位的进位的局面是无法避免的,那么你只能贪心的让高位的下一位尽可能的不进位了,也就是试着从下一位拆1。

于是构造的方法便有了

  1. 高位拆出一个1,后这个数不小于还需构造的数的个数。那么就可以用拆出来的这个1来构造出一个数
  2. 高位拆出一个1,后这个数小于还需构造的数的个数,那么只能从更低位开始判断是否可以拆出一个1

代码

#include <bits/stdc++.h>
using namespace std;
#define IOS std::ios_base::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); // 快读
typedef long long ll;

int s, n;
void solve()
{
    int k = 1;
    while (k * 10 <= s)
        k *= 10;
    while (n)
    {
        if (s - k >= n - 1) //高位拆出一个1,后这个数不小于还需构造的数的个数
        {
            if (n == 1)
                cout << s << ' '; //如果是构造的最后一个数,就输出剩下的s
            else
                cout << k << ' '; //否则输出拆出来的1
            s -= k;
            --n;
        }
        else
        {
            k /= 10; //高位拆出一个1,后这个数小于还需构造的数的个数,只能考虑从更低位拆数
        }
    }
    cout << '\n';
}

int main()
{
    IOS
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int T;
    cin >> T;

    while (T--)
    {
        cin >> s >> n;
        solve();
    }
    //system("pause");
    return 0;
}
上一篇:CF 1567D. Expression Evaluation Error


下一篇:BLEU (Bilingual Evaluation Understudy)