题解 | #小红的密码修改#
小红的密码修改
https://www.nowcoder.com/practice/209d146b415c482abf9dc5a91914f00e
输入保证原始字符串是合法的,这意味着它长度符合要求(8-16位),且同时包含大写字母、小写字母、数字、特殊符号四种类型。 当我们修改恰好一个字符时,字符串的长度不会改变,因此长度限制(8-16)始终满足。我们需要关注的唯一约束是修改后的字符串必须依然包含全部四种字符类型。
字符集定义:
合法的字符总共有 种:
- 大写字母:26个
- 小写字母:26个
- 数字:10个
- 特殊符号:4个 (
,,.,?,!)
分类讨论逻辑:
对于字符串中的每一个位置 ,假设该位置的原字符为
,其类型为
。我们需要统计将
替换为
(
) 且保持合法的方案数。
这取决于 是否是该类型
在字符串中唯一的存在:
-
情况 A:该类型的字符在字符串中出现次数 > 1
- 这意味着即使我们将位置
的字符
替换成其他类型的字符,字符串中依然还有其他字符属于类型
。
- 因此,四种类型的完整性不会被破坏。
- 我们可以将
替换为字符集中的任意其他字符。
- 该位置的贡献方案数 = 总字符数(66) - 1 (排除自己) = 65。
- 这意味着即使我们将位置
-
情况 B:该类型的字符在字符串中出现次数 == 1
- 这意味着
是类型
的“独苗”。
- 如果我们把
替换成其他类型的字符,新字符串将不再包含类型
,导致非法。
- 因此,为了保持合法,我们只能将
替换为同类型的其他字符。
- 该位置的贡献方案数取决于
的集合大小:
- 若为大写字母:
- 若为小写字母:
- 若为数字:
- 若为特殊符号:
- 若为大写字母:
- 这意味着
代码实现
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
string s;
cin >> s;
array<int, 4> cnt{};
for (char c : s) {
if (c >= 'A' && c <= 'Z')
cnt[0]++;
else if (c >= 'a' && c <= 'z')
cnt[1]++;
else if (c >= '0' && c <= '9')
cnt[2]++;
else
cnt[3]++;
}
ll ans = 0;
for (char c : s) {
if (c >= 'A' && c <= 'Z')
ans += (cnt[0] > 1) ? 65 : 25;
else if (c >= 'a' && c <= 'z')
ans += (cnt[1] > 1) ? 65 : 25;
else if (c >= '0' && c <= '9')
ans += (cnt[2] > 1) ? 65 : 9;
else
ans += (cnt[3] > 1) ? 65 : 3;
}
cout << ans << endl;
}
}
#大学最后一个寒假,我想……#每日一题@牛客网 文章被收录于专栏
牛客网每日一题