F. Dasha and Nightmares
F. Dasha and Nightmares
Dasha, an excellent student, is studying at the best mathematical lyceum in the country. Recently, a mysterious stranger brought words consisting of small latin letters to the lyceum. Since that day, Dasha has been tormented by nightmares.
Consider some pair of integers (). A nightmare is a string for which it is true:
- It is obtained by concatenation ;
- Its length is odd;
- The number of different letters in it is exactly ;
- The number of occurrences of each letter that is in the word is odd.
For example, if "abcdefg" and "ijklmnopqrstuvwxyz", the pair creates a nightmare.
Dasha will stop having nightmares if she counts their number. There are too many nightmares, so Dasha needs your help. Count the number of different nightmares.
Nightmares are called different if the corresponding pairs are different. The pairs and are called different if or .
Input
The first line contains a single integer () — the number of words.
The following lines contain the words , consisting of small latin letters.
It is guaranteed that the total length of words does not exceed .
Output
Print a single integer — the number of different nightmares.
Example
input
10 ftl abcdefghijklmnopqrstuvwxy abcdeffghijkllmnopqrsttuvwxy ffftl aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyy thedevid bcdefghhiiiijklmnopqrsuwxyz gorillasilverback abcdefg ijklmnopqrstuvwxyz
output
5
Note
In the first test, nightmares are created by pairs , , , , .
解题思路
枚举优化题,一般都会用到哈希表。
首先要发现一个隐藏的性质,就是如果拼接的字符串同时满足只有个字母和每个字母出现奇数次这两个条件,那么这个拼接的字符串自然就满足长度为奇数的条件(因为奇数乘奇数等于奇数)。因此我们并不需要关注长度为奇数这个条件,而只关注剩下的那两个条件。
由于我们只关注每个字符串中出现了那些字母以及每个字符出现的奇偶性,而最多就只有个字母,因此很自然想到用状态压缩,把映射到。对于第个字符串,定义为中出现的字母的状态,如果字母出现过,那么的第位应该为,否则为。定义为每个字母出现次数奇偶性的状态,如果字母出现了奇数次,那么的第位应该为,否则为。
对于一个合法的拼接字符串,很明显的所表示的状态中应该有个,所表示的状态中应该也有个,且是的位置都是一样的,即恰好有一个位为且是同一个位,假设对应字母。由于合法的拼接字符串状态少,因此我们就可以枚举,一共有个,来表示拼接的字符串中缺少了哪个字母,对应的。然后对于每个,枚举每一个字符串,很明显对应的的第位应该为。然后看看前面有多少个,满足的第位为,且有,即。因此可以开个哈希表来统计。
AC代码如下,时间复杂度为:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 2e5 + 10; 7 8 int a[N], b[N]; 9 int mp[1 << 26]; 10 11 int main() { 12 int n; 13 cin >> n; 14 for (int i = 0; i < n; i++) { 15 string s; 16 cin >> s; 17 for (auto &c : s) { 18 a[i] |= 1 << c - 'a'; 19 b[i] ^= 1 << c - 'a'; 20 } 21 } 22 LL ret = 0; 23 for (int c = 0; c < 26; c++) { 24 int st = (1 << 26) - 1 - (1 << c); 25 memset(mp, 0, sizeof(mp)); 26 for (int i = 0; i < n; i++) { 27 if (~(a[i] >> c) & 1) { 28 mp[b[i]]++; 29 ret += mp[st ^ b[i]]; 30 } 31 } 32 } 33 cout << ret; 34 35 return 0; 36 }
参考资料
Codeforces Round #855 (Div. 3) F:https://zhuanlan.zhihu.com/p/610978167
Codeforces Round 855 (Div. 3) Editorial:https://codeforces.com/blog/entry/113477
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17178545.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效