#include <iostream> #include <string> using namespace std; // 判断一个数字是否是3的倍数 bool isDivisibleBy3(int sum) { if(sum == 0){ return false; } return sum % 3 == 0; } // 去除字符串的前导0 string removeLeadingZeros(string& num) { int i = 0; while (i < num.length() && num[i] == '0') { i++; } return num.substr(i); // 返回去掉前导0后的子字符串 } int maxDeleteOperations(string num) { int deleteCount = 0; // 计算原始数字的数字和 int sum = 0; for (char c : num) { sum += c - '0'; } while (num.length() > 1) { bool found = false; // 尝试删除每一位数字 for (int i = num.length() - 1; i >= 0; i--) { // 更新数字和 int newSum = sum - (num[i] - '0'); // 检查删除该位后的数字和是否是3的倍数 if (isDivisibleBy3(newSum)) { num = num.substr(0, i) + num.substr(i + 1); // 删除i位置的数字 num = removeLeadingZeros(num); // 去除前导0 sum = 0; for (char c : num) { // 更新新的数字和 sum += c - '0'; } deleteCount++; // 计数 found = true; break; // 找到合适的删除位置,退出当前循环 } } // 如果找不到合适的删除位置,停止 if (!found) { break; } } return deleteCount; } int main() { int T; cin >> T; // 输入数据组数 while (T--) { string n; cin >> n; // 输入正整数n cout << maxDeleteOperations(n) << endl; // 输出最多可以删除的次数 } return 0; }
感觉牛客的题解很不友好,总感觉看着怪怪的 orz
大致思路就是如上 写了注释。大致思路就是 emm ,首先,判断是不是3的倍数 他有这样一个性质嘛,他的和是3的倍数 那么 这个数就是3的倍数,,0除外。 先算出总和, 然后对当前字符串进行一个一个枚举,判断除去这个数之后的和还是不是三的倍数 如果是3的倍数,那么这个数可以被删除,然后拼接新的字符串,再除去前导0。如果遍历一遍还没有发现可以删去的数字,那么我们直接输出答案即可。 大致思路是这样的,此外我不会算 这个时间复杂度是多少,emm会不会被hack 欢迎大佬指点