zoukankan      html  css  js  c++  java
  • [Sdoi2013] [bzoj 3198] spring (hash+容斥原理)

    题目描述

    给出nn66维坐标,求有多少对点对满足恰好mm个位置相等
    1<=n<=1051<=n<=10^5
    0<=k<=60<=k<=6
    坐标数值在2302^{30}以内

    题目分析

    这道题一看就是hash容斥原理,用mm个位置对应相等(m+1)-(m+1)个位置对应相等+(m+2)+(m+2)个位置对应相等的…
    但是不能简简单单直接+/+/-,根据广义容斥,还要乘上容斥系数CkmC_{k}^{m}
    HashHash,过程中遇到Hash1Hash1相同但Hash2Hash2不同的就往后平移,用数组存一下Hash1Hash1kk时的Hash2Hash2值与CntCnt
    注意此处ModMod数要大于nn

    考试时没用双Hash,想到了做法,奈何代码太丑,这题爆0了…

    AC code
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    const int MAXN = 100005;
    const int P1 = 137, Mod1 = 9999997;
    const int P2 = 167, Mod2 = 7394895;
    int num[MAXN][6], c[7][7], kase, n, m;
    struct MyHash
    {
    	LL y; int flag, cnt; //y存的是Hash1为当前下标i时的Hash2值
    	//flag是用int打标记,就不用每次清零了
    	bool Exist() { return flag == kase; }
    }h[Mod1];
    LL Ans;
    void init()
    {
    	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];
    	}
    }
    
    inline void MyUnique(LL &x, LL o)
    {
    	while(h[x].Exist() && h[x].y != o) (++x) %= Mod1;
    }
    
    bool used[7];
    void dfs(int pos, int tot)//枚举当前是求哪几个位置
    {
    	if(pos == 6)
    	{
    		if(tot < m) return; //小于m的不用处理
    		LL sum = 0; ++kase;
    		for(int i = 1; i <= n; ++i)
    		{
    			LL hsh1 = 0, hsh2 = 0;
    			for(int j = 0; j < 6; ++j) if(used[j])
    				hsh1 = (hsh1 * P1 % Mod1 + num[i][j]) % Mod1,
    				hsh2 = (hsh2 * P2 % Mod2 + num[i][j]) % Mod2;
    			MyUnique(hsh1, hsh2);
    			if(h[hsh1].flag < kase)
    				h[hsh1].cnt = 0, h[hsh1].flag = kase;
    			h[hsh1].y = hsh2, sum += (h[hsh1].cnt++);
    		}
    		Ans += sum * (((tot-m)&1) ? -1 : 1) * c[tot][m]; //容斥
    		return;
    	}
    	used[pos] = 1;
    	dfs(pos+1, tot+1);
    	used[pos] = 0;
    	dfs(pos+1, tot);
    }
    
    int main ()
    {
    	scanf("%d%d", &n, &m); init();
    	for(int i = 1; i <= n; ++i)
    		for(int j = 0; j < 6; ++j)
    			scanf("%d", &num[i][j]);
    	dfs(0, 0);
    	printf("%lld
    ", Ans);
    }
    
  • 相关阅读:
    《Mysql
    《Redis
    《pt-query-digest 剖析 Mysql 慢日志》
    《Redis
    《Redis
    《Redis
    《Redis
    《Redis
    python中__new__()与__init__()的区别
    Python常见综合面试题
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039469.html
Copyright © 2011-2022 走看看