题目描述
在顺利完成家庭作业以后,Mirko感到非常的厌倦。所以,他列出了N个数,这些数中有些数对他是喜欢的,有些数对他是不喜欢的。
他喜欢的数对叫做友好数对,如果两个数至少有一个相同的数字(不要求在相同的位置),那么这两个数就是友好数对。请帮助Mirko在这N个数找出有多少友好数对。
输入
第一行一个正整数N(1<=N<=1000000)。
接下来N行,每行一个正整数,范围在1到1018之间。N个数中任意两个数都是不同的。
输出
只有一行一个整数,表示友好数对的个数。
分析
友好数对一点都不友好。。
这题没得暴力。。经讲解,这题是容斥原理(上个友链)。因为最多不超过1023((1<<10)-1),数组就开1024。然后存对应位。循环一下,是0就不做,然后判断i,j相等关系,不相等直接乘。然后在一层循环的最后,补上乘。
注意:最后输出ans的时候要玄学/2,我也不知道为啥。。。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long num[1024],n,s,f[1024],ans,sum;
int main()
{
freopen("kompici.in","r",stdin);
freopen("kompici.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)
{
long long x,y,z;
cin>>x;
z=0;
while(x>0)
{
y=x%10;
x=x/10;
z=z|(1<<y);
}
num[z]++;
}
for(int i=1;i<=1023;i++)
{
if(num[i]==0) continue;
for(int j=1;j<=1023;j++)
{
if((i&j)!=0&&num[j]>0&&i!=j)
{
ans+=num[i]*num[j];
}
}
ans+=num[i]*(num[i]-1);
}
cout<<ans/2;
fclose(stdin);
fclose(stdout);
return 0;
}