zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    HDU2586 How far away?(tarjan的LCA)
    You Raise Me Up
    POJ2891 Strange Way to Express Integers(中国剩余定理)
    POJ2142 The Balance(扩展欧几里得)
    HDU 1166模仿大牛写的线段树
    NetWord Dinic
    HDU 1754 线段树裸题
    hdu1394 Minimum Inversion Number
    hdu2795 Billboard
    【完全版】线段树
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5239037.html
Copyright © 2011-2022 走看看