bzoj3198[Sdoi2013]spring 容斥+hash

3198: [Sdoi2013]spring

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 1143  Solved: 366
[Submit][Status][Discuss]

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

Dragonite修正数据

Source

Hash

 

容斥简单,但是hash有点麻烦。
ans= 至少k的对数*C(k,k) - 至少k+1的对数*C(k+1,k) + 至少k+2的对数*C(k+2,k) ...
对于这个C(i+k,k),我的理解这对数被计算了C(k+i,k)次
hash判断冲突。。至少我不会,别人博客学习了一波

 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
#define N 100005
#define mod 2150527
using namespace std;
int a[N][10],bin[10],hd[mod+10],vis[mod+10],c[10][10],sum[N],nxt[N],n,m;
ll val[N];
void pre(){
    for(int i=0;i<=6;i++)c[i][0]=c[i][i]=1;
    for(int i=1;i<=6;i++)
    for(int j=1;j<i;j++)
    c[i][j]=c[i-1][j-1]+c[i-1][j];
}
ll calc(int st){
    ll ans=0;int tot=0;
    for(int i=1;i<=n;i++){
        ll tmp=0;int j,k;
        for(j=1;j<=6;j++)if(st&bin[j-1])tmp=tmp*1000003+a[i][j];
        j=tmp%mod;j<0?j+=mod:1;
        if(vis[j]!=st){vis[j]=st;hd[j]=0;}
        for(k=hd[j];k;k=nxt[k]){
            if(val[k]==tmp){
                ans+=sum[k];sum[k]++;
                break;
            }
        }
        if(!k){
            val[++tot]=tmp;
            sum[tot]=1;nxt[tot]=hd[j];hd[j]=tot;
        }
    }
    return ans;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=6;j++)
    scanf("%d",&a[i][j]);
    bin[0]=1;pre();
    for(int i=1;i<=8;i++)bin[i]=bin[i-1]<<1;
    ll ans=0;
    for(int i=0;i<64;i++){
        int cnt=0;
        for(int j=0;j<6;j++)
        if(i&bin[j])cnt++;
        if(cnt<m)continue;
        ll t=calc(i)*c[cnt][m];
        if((cnt-m)%2)ans-=t;
        else ans+=t;
    }
    cout<<ans;
    return 0;
}
posted @ 2017-12-11 17:00  _wsy  阅读(319)  评论(0编辑  收藏  举报