专栏文章
CF1287B 题解
CF1287B题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minbwgn6
- 此快照首次捕获于
- 2025/12/01 23:53 3 个月前
- 此快照最后确认于
- 2025/12/01 23:53 3 个月前
题意
给出 个仅包含字母 “”、“”、“” 且长度为 的字符串,求出有多少种方式可以使这三个字符串的该特征(字母)要么全部相同,要么两两不同。
解答
通过观察样例可以发现,如果已知两张卡片那么最后一张卡片有且仅有一张。
证明,两个字符串按照每个字符一一对应,那么第三个字符串中的字符仅有两种情况(要么全部相同,要么两两不同):
- 若两个字符相同,那么第三个字符肯定与前两个字符一样。(全部相同)
- 若两个字符不同,那么第三个字符仅可能是“”、“”、“” 中除那两个字符的剩下一个字符。(两两不同)
例如,两个字符串分别为为 和 。 设 为字符串的下标,则:
-
当 ,答案是除 和 的另外一个字符,即 ;
-
当 ,两个字符都是 ,因此答案是 ;
-
当 ,答案是除 和 的另外一个字符,即 ;
-
当 ,两个字符都是 ,因此答案是 。
故最后一个字符串是 ,是唯一的。
那么我们用一个 统计每个字符串出现的次数,之后只需要枚举两个字符串 ,。 计算出它们需要组成一个 set 的另一个字符串,查看在 中出现了几次,计入答案。
这样计算会出现问题,我们会重复计算答案,怎么处理呢?
-
问题1:我们计算出的第三个字符串可能与前两个就是同一个字符串。解答:不需要计入这个答案,将
ans--。 -
问题2:假设有三张卡片 A、B、C 能组成一个 set。在双重循环遍历每一张卡牌中,这个 set 会被计数 次:
-
当 set 的前两张卡牌为 时,推导出的第三张卡片是 ;
-
当 set 的前两张卡牌为 时,推导出的第三张卡片是 ;
-
当 set 的前两张卡牌为 时,推导出的第三张卡片是 。
解答:每个合法的 set 都会被计数 次,所以最后只需要除以 来消除重复计数。 -
代码
CPP#include<bits/stdc++.h>
using namespace std;
unordered_map<string, int> mp;
string s[1505];
// 找到除两个字母以外的剩下一个字母
char check(char a, char b)
{
bool t[10] = {0};
char x[5] = {'S', 'E', 'T'};
for(int i=0; i<=2; i++)
if(a == x[i] || b == x[i]) t[i] = 1;
for(int i=0; i<=2; i++)
if(t[i] == 0) return x[i];
}
int main()
{
int n, k; cin >> n >> k;
for(int i=1; i<=n; i++) cin >> s[i], mp[s[i]]++;
int ans = 0;
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++)
{
string a = s[i], b = s[j], c = "";
for(int l=0; l<k; l++)
if(a[l] == b[l]) c += a[l]; // 全部相同
else c += check(a[l], b[l]); // 两两不同
ans += mp[c];
// 解决重复计算的问题 1
if(a == c) ans --;
if(b == c) ans --;
}
// 解决重复计算的问题 2
cout << ans / 3 << endl;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...