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,后这个数小于还需构造的数的个数,那么只能从更低位开始判断是否可以拆出一个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;
}