Solution
考虑转化题目条件,因为要求字符串恰好有 \(25\) 个字符,所以考虑枚举没出现过的字符,令其为 \(k\)。再令 \(f_{i,p}\) 表示第 \(i\) 个字符串 \(p\) 字符出现次数的奇偶,于是题目条件即为:
- \(f_{i,k}=f_{j,k}=0\)。
- \(f_{i,p}+f_{j,p} \bmod 2=1\)。
于是考虑用一个 \(2^{26}\) 的桶或 bitset
表示出每个字符串,即如果 \(f_{i,p} \bmod 2=1\),\(num \gets num+2^p\),把 \(num\) 放入桶,统计答案的时候将 \(f_{i,p} \bmod 2=0\) 的 \(j\) 加入 \(num\) 即可,时间复杂度为 \(O(nV^2)\),\(V\) 为 \(26\)。
#include<bits/stdc++.h>
#define ll long long
#define x first
#define y second
#define il inline
#define debug() puts("-----")
using namespace std;
typedef pair<int,int> pii;
const int N=2e5+10,M=26;
int n;
int f[N][M];
string s[N];
int mp[1<<M];
bool st[N][M];
il void work(){
cin>>n; ll ans=0;
for(int i=1;i<=n;i++){
cin>>s[i];
for(int j=0;j<M;j++) f[i][j]=0;
for(int j=0;j<s[i].size();j++) f[i][s[i][j]-'a']++,st[i][s[i][j]-'a']=true;
} for(int k=0;k<M;k++){
for(int i=1;i<=n;i++){
if(st[i][k]) continue; int num=0;
for(int j=0;j<M;j++) if(f[i][j]&1) num+=(1<<j);
mp[num]++;
} for(int i=1;i<=n;i++){
if(st[i][k]) continue; int num=0;
for(int j=0;j<M;j++) if(j!=k&&(!(f[i][j]&1))) num+=(1<<j);
ans+=1ll*mp[num];
} for(int i=1;i<=n;i++){
if(st[i][k]) continue; int num=0;
for(int j=0;j<M;j++) if(f[i][j]&1) num+=(1<<j);
mp[num]--;
}
} printf("%lld\n",ans/2);
}
signed main(){
int T=1;
while(T--) work(); return 0;
}
标签:26,CF1800F,int,题解,bmod,num,字符串,define
From: https://www.cnblogs.com/Celestial-cyan/p/18054722