您的位置:首页 > 编程语言 > Java开发

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

2016-03-03 16:12 501 查看

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 :)

【代码】

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
const int N = 1001001;
const int B = 999911657;

namespace Hash_set
{
struct node {
node* nxt;
ull H; int v;
node(){}
node(node* _,ull __) :
nxt(_),H(__),v(0) {}
}*head
,mempool
,*C=mempool;
int vis
,kase;
void init() {
kase++; C=mempool;
}
int& insert(ull st) {
int pos=st%1001001;
if(vis[pos]!=kase) {
vis[pos]=kase; head[pos]=0x0;
}
for(node* p=head[pos];p;p=p->nxt)
if(p->H==st) return p->v;
head[pos]=new (C++) node(head[pos],st);
return head[pos]->v;
}
}

int n,K,a
[6],C[7][7];

ll calc(int st)
{
using namespace Hash_set;
ll ans=0;
init();
for(int i=0;i<n;i++) {
ull hash=0;
for(int j=0;j<6;j++)
if( st&(1<<j) )
hash=(hash*B+a[i][j]);
int& val=insert(hash);
ans+=(val++);
}
return ans;
}

void get_C()
{
for(int i=0;i<=7;i++) {
C[i][0]=C[i][i]=1;
for(int j=1;j<i;j++)
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
}

void read(int& x) {
char c=getchar(); int f=1; x=0;
while(!isdigit(c)){if(c=='-')f=-1; c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
}

int main()
{
get_C();
read(n),read(K);
for(int i=0;i<n;i++)
for(int j=0;j<6;j++) read(a[i][j]);
ll ans=0;
for(int i=0;i<64;i++) {
int cnt=0;
for(int j=0;j<6;j++)
if(i&(1<<j)) cnt++;
if(cnt>=K) ans+=((cnt-K)&1?-1:1)*calc(i)*C[cnt][K];
}
printf("%lld",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: