Codeforces 1352A:最小圆形数之和表示问题解法问询
问题定义
若一个正整数(严格大于0)形如d00...0,即除最高位外其余数位均为0,则称其为圆形数(round number)。1-9的整数均为圆形数。例如4000、90是圆形数,110、707不是。
给定正整数n(1≤n≤10⁴),需将n表示为最少个数的圆形数之和。
输入输出格式
- 输入:第一行是测试用例数t(1≤t≤10⁴),随后t行每行一个整数n。
- 输出:每组输出最少求和项数k,再输出k个圆形数,和为n。
用户提供的解法代码
#include<iostream> #include<algorithm> #include<vector> #define in(x) cin>>x #define out(x) cout<<x #define vi vector<int> #define pb push_back #define testCase \ int t; \ cin>>t; \ while(t--) using namespace std; int main() { testCase{ vi v{1000,100,10, 1}; vi ans; int n; in(n); for(int i: v){ if(n>=i){ if(n>0 && n<=i) ans.pb(n); else ans.pb(n-(n%i)); n%=i; } } out(ans.size()<<endl); for(int i: ans){ out(i<<" "); } out(endl); } return 0; }
解法正确性分析
你的解法逻辑方向是对的,但存在一个隐蔽的输出bug:out(ans.size()<<endl);中,位运算<<的优先级高于流输出,会先计算ans.size()左移endl的数值,导致输出错误的项数。修正为out(ans.size()) << '\n';后,解法是正确的。
核心逻辑的正确性:要得到最少圆形数之和,本质是拆分n的每一位非零数字对应的位值(比如567拆为500+60+7),这是理论最小值——每个非零数位至少需要一个圆形数覆盖。你的代码通过遍历高位到低位的位值,提取对应部分,正好符合这个要求。
更优实现方式
可以简化逻辑,同时优化输入输出效率,适配大规模测试用例:
#include<iostream> #include<vector> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { int n; cin >> n; vector<int> res; int power = 1; while (n > 0) { int digit = n % 10; if (digit != 0) { res.push_back(digit * power); } n /= 10; power *= 10; } cout << res.size() << '\n'; for (int num : res) { cout << num << ' '; } cout << '\n'; } return 0; }
该实现的优势:
- 逻辑更直观:直接按数位拆分,提取每个非零数字对应的圆形数,无需额外条件判断。
- 扩展性更强:若n的范围扩大(比如到10^9),无需修改位值列表,循环会自动适配。
- 输入输出优化:
ios::sync_with_stdio(false); cin.tie(nullptr);消除C++与C标准IO的同步开销,更适合t=1e4的大规模测试。
内容的提问来源于stack exchange,提问作者Fahad
相关产品推荐
相关产品推荐

