题意:
给你一些只含3个字符的字符串(只有字母表中前24个字符),现在自定义元音字符,如果一个字符串中含有至少一个元音字符,那么称为这个字符串是有效的,现在问你对于 2 24 2^{24} 224种元音定义的可能,输出每种可能性所含有效元音字符串的平方异或和。
题解:
SOSDP的本质就是高位前缀和,那么对于这道题,我们只需要判断一下每个字符串中有哪些不同的有效状态即可,同时要使用容斥,因为对于110这种状态,它会从100和010两种状态转移过来。
#include<bits/stdc++.h>
using namespace std;
const int N=1<<24;
int dp[N];
int main()
{
int n;
scanf("%d",&n);
char s[5];
for(int i=1;i<=n;i++)
{
scanf("%s",s);
dp[1<<(s[0]-'a')]++;
if(s[1]!=s[0])
{
dp[1<<(s[1]-'a')]++;
dp[(1<<(s[1]-'a'))|(1<<(s[0]-'a'))]--;
}
if(s[2]!=s[1]&&s[2]!=s[0])
{
dp[1<<(s[2]-'a')]++;
dp[(1<<(s[1]-'a'))|(1<<(s[2]-'a'))]--;
if(s[1]!=s[0])
dp[(1<<(s[0]-'a'))|(1<<(s[2]-'a'))]--;
}
if(s[2]!=s[1]&&s[1]!=s[0]&&s[2]!=s[0])
dp[(1<<(s[0]-'a'))|(1<<(s[1]-'a'))|(1<<(s[2]-'a'))]++;
}
int ans=0;
for(int i=0;i<24;i++)
for(int j=0;j<N;j++)
if(j&(1<<i))
dp[j]+=dp[j^(1<<i)];
for(int i=1;i<N;i++)
ans^=(dp[i]*dp[i]);
printf("%d\n",ans);
return 0;
}