山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 3198 [Sdoi2013]spring(容斥原理+Hash)

 

Description

 

Input

Output

Sample Input

3 3
1 2 3 4 5 6
1 2 3 0 0 0
0 0 0 4 5 6

Sample Output

2

HINT

 

 

【思路】

 

       容斥原理+Hash

       恰有k个元素相同的对数=至少k+1个相同*C(k+1,k) - 至少k+2个相同*C(k+2,k) + ……

       枚举状态i,如果是101表示至少1和3两个相同,把n个年份关于i构造一个hash,然后放入hash中统计。这里只是关于位是1的构造hash,其他位都忽略了,所以得到的是至少有多少个相同的数目。

       学了个hash表的写法,新姿势get :)

 

【代码】

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 typedef unsigned long long ull;
 8 typedef long long ll;
 9 const int N = 1001001;
10 const int B = 999911657;
11 
12 namespace Hash_set 
13 {
14     struct node {
15         node* nxt;
16         ull H; int v;
17         node(){}
18         node(node* _,ull __) :
19             nxt(_),H(__),v(0) {}
20     }*head[N],mempool[N],*C=mempool;
21     int vis[N],kase;
22     void init() {
23         kase++; C=mempool;
24     }
25     int& insert(ull st) {
26         int pos=st%1001001;
27         if(vis[pos]!=kase) {
28             vis[pos]=kase; head[pos]=0x0;
29         }
30         for(node* p=head[pos];p;p=p->nxt)
31             if(p->H==st) return p->v;
32         head[pos]=new (C++) node(head[pos],st);
33         return head[pos]->v;
34     }
35 }
36 
37 int n,K,a[N][6],C[7][7];
38 
39 ll calc(int st) 
40 {
41     using namespace Hash_set;
42     ll ans=0;
43     init();
44     for(int i=0;i<n;i++) {
45         ull hash=0;
46         for(int j=0;j<6;j++)
47             if( st&(1<<j) )
48                 hash=(hash*B+a[i][j]);
49         int& val=insert(hash);
50         ans+=(val++);
51     }
52     return ans;
53 }
54 
55 void get_C() 
56 {
57     for(int i=0;i<=7;i++) {
58         C[i][0]=C[i][i]=1;
59         for(int j=1;j<i;j++)
60             C[i][j]=C[i-1][j-1]+C[i-1][j];
61     }
62 }
63 
64 void read(int& x) {
65     char c=getchar(); int f=1; x=0;
66     while(!isdigit(c)){if(c=='-')f=-1; c=getchar();}
67     while(isdigit(c)) x=x*10+c-'0',c=getchar();
68 }
69 
70 int main()
71 {
72     get_C();
73     read(n),read(K);
74     for(int i=0;i<n;i++)
75         for(int j=0;j<6;j++) read(a[i][j]);
76     ll ans=0;
77     for(int i=0;i<64;i++) {
78         int cnt=0;
79         for(int j=0;j<6;j++)
80             if(i&(1<<j)) cnt++;
81         if(cnt>=K) ans+=((cnt-K)&1?-1:1)*calc(i)*C[cnt][K];
82     }
83     printf("%lld",ans);
84     return 0;
85 }

 

posted on 2016-03-03 16:12  hahalidaxin  阅读(250)  评论(0编辑  收藏  举报