CF1045I Palindrome Pairs 题解

题目传送门~

题目分析

首先得出两个串加在一起构成回文的要求:最多只有 1 个字母总共有奇数个

想也很好想,同个字母两两对应,对应不了的那个放中间就行。

然后我们发现每个字符串只需要存储每个字母的数量的奇偶性 0,1 两个量,很容易想到用一个 26 位二进制来存字符串。

满足要求的对数可以分成两种情况考虑:

  1. 每个字母总共都是偶数个。

观察下列式子:0+0=0,1+1=2

可以发现只有二进制数相等的两个字符串可以构成这种情况,开一个数组记录每个二进制数的个数。然后这其中任选两个都能构成回文,即贡献为 Cn2

  1. 有且仅有一个字母为奇数个。

也很容易得出两个字符串的二进制仅有一个位不同。那么也只需要开一个哈希记录每一个二进制数可以被“匹配”的数量(“匹配”即为仅有一个位不同)。然后贡献为每个字符串对应的二进制数被“匹配”的个数。

最后答案为上述两种情况的和。

代码

#include<bits/stdc++.h>
using namespace std;
unordered_map<long long,long long> mp,ct;
vector<long long> v;
long long n,x,res;
int main()
{
    scanf("%lld",&n);
    for (int e = 1;e <= n;e++)
    {
        x = 0;//将字符串存为一个二进制数
        string s;cin >> s;
        for (int i = 0;i < s.size();i++) x ^= (1 << (s[i]-'a'));//存第s[i]位
        v.push_back(x);
        for (int i = 0;i < 26;i++) 
            if (((x >> i) & 1) == 0) 
                ct[(x+(1 << i))]++; //第i位不同的匹配
        mp[x]++; 
    }
    for (auto e:mp) res += e.second*(e.second-1)/2; //偶数的情况贡献为cn2
    for (auto t:v) res += ct[t]; // 可以被匹配
    cout << res <<endl;
    return 0;
}
posted @   codwarm  阅读(9)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示