1 条题解
-
0
思路
题意简述:每次操作可以给 加上一个十进制表示全由数字 9 组成的正整数(),可以操作任意多次。求最少的操作次数,使得结果中至少有一位是 7。
先看一次操作的效果。任意一个全 9 的数都可以写成
也就是说,它在个位上减 1,同时在从右往左第 位上“加 1”。做 次操作后:
$$n+\sum_{i=1}^{l}(10^{p_i}-1)=n-l+\sum_{i=1}^{l}10^{p_i}.$$因此可以把过程理解为:
- 先在个位上统一减掉 ,得到基础数 ;
- 再把 个“加一”分配给较高的数位(每个操作贡献一个 )。
要让结果中出现 7,最省“加一”的办法是:在 中找一个不超过 7 的数位 ,把 个增量加在这一位上,使它恰好变成 7;剩余的增量可以加到更高位的新列上,不会破坏已经得到的 7。数字 8、9 只会继续增大(产生进位),不能直接变成 7,所以不参与选择。
于是设 为 中不超过 7 的最大数位, 次操作可行的条件就是
从小到大枚举 ,第一个满足条件的 就是最少操作次数。
关于枚举范围: 时一定有 (),且 保证 ,所以答案一定不超过 7,循环到 9 足够。 则覆盖了 本身已含 7 的情况(此时 ,条件 成立)。
复杂度:每组数据只枚举 10 次,每次处理 个数位,总时间 ,空间 (字符串开销)。
代码
#include<bits/stdc++.h> #define int long long #define dd double #define str string #define el cout << endl #define re return #define ff first #define ss second #define pll pair<int,int> #define pdd pair<dd,dd> #define all(x) x.begin(),x.end() #define pb push_back #define sz(x) (int) x.size() using namespace std; void go(){ int n; cin >> n; // 从小到大枚举操作次数 l,第一个可行的 l 即为答案 for (int l = 0; l <= 9; l++) { // l 次操作先贡献个位上的 -l,得到基础数 n-l string s = to_string(n - l); // md 记录 n-l 中不超过 7 的最大数位(8、9 无法直接变成 7,忽略) int md = 0; for (auto c: s) { if (c <= '7') { md = max(md, (int)(c - '0')); } } // 把该数位补到 7 需要 7-md 次“加一”,l 足够即可行 if (l >= 7 - md) { cout << l << '\n'; return; } } } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr);cout.tie(nullptr); int t=1; cin >>t; // 多组测试数据 while(t--){ go(); } return 0; }
- 1
信息
- ID
- 50
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者