对于 100%的数据,n<=50000,k<=4
————————————————————————————————
【题解】【字符串哈希+容斥】
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; int hash[50010],sum[50010][4]; ll ans[5]; int n,k; inline int change(char x) { if(x>='0'&&x<='9') return x-'0'; return x-'a'+10; } inline ll cal(int n) { ll sm=0; int i,x=1; sort(hash+1,hash+n+1); for(i=2;i<=n;++i) if(hash[i]==hash[i-1]) x++; else sm+=(ll)(x-1)*x/2,x=1; sm+=(ll)(x-1)*x/2; return sm; } int main() { freopen("pearls.in","r",stdin); freopen("pearls.out","w",stdout); int i,j,l; scanf("%d%d",&n,&k); for(i=1;i<=n;++i) { char s[5]; scanf("%s",s); for(j=0;j<4;++j) sum[i][j]=change(s[j]); } for(i=1;i<=n;++i) for(j=0;j<4;++j) hash[i]=hash[i]*36+sum[i][j]; ans[0]=cal(n); for(l=0;l<4;++l) { memset(hash,0,sizeof(hash)); for(i=1;i<=n;++i) { for(j=0;j<l;++j) hash[i]=hash[i]*36+sum[i][j]; for(j=l+1;j<4;++j) hash[i]=hash[i]*36+sum[i][j]; } ans[1]+=cal(n); } ans[1]-=ans[0]*4; if(k==1) {printf("%I64d\n",ans[1]); return 0;} for(l=0;l<4;++l) for(i=l+1;i<4;++i) { for(j=1;j<=n;++j) hash[j]=sum[j][l]*36+sum[j][i]; ans[2]+=cal(n); } ans[2]-=(ans[0]*4+ans[1]*3); if(k==2) {printf("%I64d\n",ans[2]); return 0;} for(l=0;l<4;++l) { for(i=1;i<=n;++i) hash[i]=sum[i][l]; ans[3]+=cal(n); } ans[3]-=(ans[2]*2+ans[1]*3+ans[0]*4); if(k==3) {printf("%I64d\n",ans[3]); return 0;} ans[4]=(ll)(n-1)*n/2-ans[3]-ans[2]-ans[1]-ans[0]; printf("%I64d\n",ans[4]); return 0; }