URAL 1932 The Secret of Identifier (dp+容斥,4级)

B - The Secret of Identifier
Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Description

Davy Jones: You've been captain of the Black Pearl for 13 years. That was our agreement.
Jack: Technically I was only captain for two years, then I was mutinied upon.
Davy Jones: Then you were a poor captain, but a captain nonetheless. Have you not introduced yourself as Captain Jack Sparrow?
According to the Pirate Code, each of the pirates of the Caribbean at the beginning of their professional career (hereditary pirates –– at birth) is assigned by a unique identifier. Pirate's identifier is a string of four hexadecimal digits. However, it is not a usual row of numbers, it is said that personal qualities and life path of its owner are encoded in it by a mysterious way. But no one still could guess this mystical connection.
Once Captain Jack Sparrow, while sitting in captain’s cabin, decided to try to find the way to derive some data about a pirate using the identifier. Memories about how he lost the Black Pearl last time gave him the idea that more similar identifiers of two pirates are, bigger chances for these pirates to unite against the Captain, and, as a result, to make a mutiny. The Captain Jack Sparrow, of course, doesn’t want to have the mutiny on his ship, but he chose the new team this time and it is going to be a long voyage. Now Jack needs to estimate the opportunities of raising the mutiny on his ship, based on the conclusions. For this aim he first wants to know for each pair of pirates a number of positions in their identifiers in which they are different.

Input

The first line contains an integer n –– the number of pirates aboard the Black Pearl (2 ≤ n ≤ 65536). Each of the following n lines contains four-digit identifier of the respective pirate. Only decimal digits and lowercase Latin letters from “a” to “f” inclusive are used in writing identifiers. Identifiers of all pirates are different.

Output

Output four space separated integers –– the amount of pairs of pirates, which have different identifiers exactly in one, two, three and four positions respectively.

Sample Input

input output
3
dead
beef
f00d
0 0 2 1

思路:先压状态计算1,2,3,4 位一样的个数。dp[16][1<<16] 前面2进制位相同的个数。
          然后容斥下。
#include<iostream>
#include<cstring>
#include<cstdio>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define clr(f,z) memset(f,z,sizeof(f))
#define ll(x) (1<<x)
using namespace std;
int dp[16][ll(16)];
int N,n;
int idx(char x)
{
  if(x>='a')return x-'a'+10;
  return x-'0';
}
char s[8];
int one(int x)
{
  int ret=0;
  while(x)
  {
    if(x&1)++ret;
    x>>=1;
  }
  return ret;
}
void getans()
{ long long tmp[4],ans[4];
  clr(tmp,0);clr(ans,0);
  FOR(i,1,15)
  {
    int z=one(i);
    FOR(j,0,N)tmp[z]+=dp[i][j]*(dp[i][j]-1)/2;
  }
     ans[1] = tmp[3];//1位不同=3位相同
    ans[2] = tmp[2] - 3 * tmp[3];
    ans[3] = tmp[1] - 2 * tmp[2] + 3 * tmp[3];
    ans[4] = (long long)(n - 1) * n / 2 - ans[1] - ans[2] - ans[3];
    cout<<ans[1]<<' '<<ans[2]<<' '<<ans[3]<<' '<<ans[4]<<endl;
}
int main()
{
  while(~scanf("%d",&n))
  { clr(dp,0);N=0;
    FOR(i,1,n)
    {
      scanf("%s",s+1);
      FOR(j,0,15)
      {
        int ret=0;
        if(j&8)ret+=idx(s[1])*ll(12);
        if(j&4)ret+=idx(s[2])*ll(8);
        if(j&2)ret+=idx(s[3])*ll(4);
        if(j&1)ret+=idx(s[4]);
        ++dp[j][ret];
        N=max(N,ret);
      }
    }
    getans();
  }
}


posted @ 2013-09-03 19:29  剑不飞  阅读(200)  评论(0编辑  收藏  举报