标题效果:
计算到n字符串。
精确到只是有一个不同的字符,两个不同的字符。三个不同的字符,四对不同的字符。
IDEAS:
枚举状态。
dp[i] [j] ...当前串取出 i 状态下的全部字符转化成十进制数为 j 的出现的次数。
这种话,就记录了全部串的子串的状态。
然后计数就得到了全部的状态。
然后我们要得到精确不同的,能够用补集的思想,假设要精确到三个不同样,意味着要精确到1 个是同样的。
注意的问题是
在最后要运用容斥去重。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring> using namespace std;
typedef long long ll; char str[6];
ll dp[16][1<<16]; int trans(char ch)
{
if(isdigit(ch))return ch-'0';
return ch-'a'+10;
}
int Count(int x)
{
int ret=0;
while(x){
ret+=(x&1);
x>>=1;
}
return ret;
}
ll tmp[5],ans[5];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int maxm=-1;
memset(dp,0,sizeof dp);
memset(tmp,0,sizeof tmp); for(int i=1;i<=n;i++)
{
scanf("%s",str);
for(int s=1;s<16;s++)
{
int t=0;
if(s&8) t += trans(str[0])*(1<<12);
if(s&4) t += trans(str[1])*(1<<8);
if(s&2) t += trans(str[2])*(1<<4);
if(s&1) t += trans(str[3]);
dp[s][t]++;
maxm=max(t,maxm);
}
}
for(int s=1;s<16;s++)
{
int x=Count(s);
for(int i=0;i<=maxm;i++)
{
tmp[x]+=dp[s][i]*(dp[s][i]-1)/2;
}
} ans[1]=tmp[3];
ans[2]=tmp[2]-3*tmp[3];
ans[3]=tmp[1]-2*tmp[2]+3*tmp[3];
printf("%I64d %I64d %I64d %I64d\n",ans[1],ans[2],ans[3],(ll)n*(n-1)/2-ans[1]-ans[2]-ans[3]);
}
return 0;
}
版权声明:本文博客原创文章,博客,未经同意,不得转载。