bzoj3198 [sdoi2013] spring 哈希挂表+容斥

6这个数据非常小,而且hash只能用来匹配,并不能检验完全不匹配,对于处于对立面的小数据就需要使用大型暴力容斥

但这个题超级卡hash,不知道是数据的锅还是题目本身的性质,直接上双hash都过不了

首先hash是被hash的数规模越小越不容易错,所以对于枚举每个数容斥不如先容斥再枚举每个数,这样容斥的位数确定就可以单独使用hash,规模会小很多,所以就是用了hash挂表。先正常用long long自然溢出,然后再用一个模数来挂


码:

#include<iostream>
#include<cstdio>
using namespace std;
#define jz 1000003
#define P 2150527
int lin,n,k,er[9],xia[P+10],hou[100005];
long long a[100005][9],sum[P],c[9][9],daan,v[100005];
int vis[P];
long long work(int o)
{
	int i,j,ans=0,k,tot=0;
	for(i=1;i<=n;i++)
	{
		long long tmp=0;
		for(j=0;j<6;j++)
		if(er[j]&o)tmp=tmp*jz+a[i][j+1];
		j=tmp%P;if(j<0)j+=P;else j++;
		if(vis[j]!=o)vis[j]=o,xia[j]=0;
		   
		for(k=xia[j];k;k=hou[k]){
            if(v[k]==tmp){
                ans+=sum[k];sum[k]++;
                break;
            }
        }
        if(!k){
            v[++tot]=tmp;
            sum[tot]=1;hou[tot]=xia[j];xia[j]=tot;
        }
		
			
	}
	return ans;
}


int main()
{
	int i,j;
	scanf("%d%d",&n,&k);
	c[0][0]=1;for(i=1;i<=6;i++){c[i][0]=1;for(j=1;j<=i;j++)c[i][j]=c[i-1][j-1]+c[i-1][j];}
	er[0]=1;
	for(i=1;i<=7;i++)er[i]=er[i-1]*2;
	for(i=1;i<=n;i++)for(j=1;j<=6;j++)scanf("%lld",&a[i][j]);
	for(i=0;i<er[6];i++)
	{
		int lin=0;
		for(j=0;j<6;j++)if(i&er[j])++lin;
		if(lin<k)continue;
		long long flg=1;
		if((lin&1)!=(k&1))flg=-1;
		daan+=work(i)*c[lin][k]*flg;		
	}
	printf("%lld",daan);
	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值