zoukankan      html  css  js  c++  java
  • [SDOI2013]泉(容斥)

    /*
    容斥加上哈希
    
    首先我们可以2 ^ 6枚举相同情况, 然后对于这些确定的位置哈希一下统计方案数
    这样我们就统计出了这些不同方案的情况, 然后容斥一下就好了 
    
    */
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #define ll unsigned long long 
    #define M 101010
    #define mmp make_pair
    using namespace std;
    int read()
    {
    	int nm = 0, f = 1;
    	char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    	return nm * f;
    }
    const int mod = 100007, base = 17171;
    int n, k, a[M][7], c[7][7], cnt[131];
    
    struct Mp
    {
    	vector<pair<ll, int> > hs[M];
    	void init()
    	{
    		for(int i = 0; i < mod; i++) vector<pair<ll, int> >().swap(hs[i]);
    	}
    	
    	void insert(ll x)
    	{
    		int op = x % mod;
    		bool f = false;
    		for(int i = 0; i < hs[op].size(); i++)
    		{
    			if(x == hs[op][i].first)
    			{
    				hs[op][i].second++;
    				f = true;
    				break;
    			}
    		}
    		if(!f) hs[op].push_back(mmp(x, 1));
    	}
    	
    	ll calc()
    	{
    		ll ans = 0;
    		for(int i = 0; i < mod; i++)
    		{
    			for(int j = 0; j < hs[i].size(); j++)
    			{
    				int x = hs[i][j].second;
    				ans += 1ll * x * (x - 1) / 2;
    			}
    		}
    		return ans;
    	}
    }mp;
    
    ll work(int x)
    {
    	mp.init();
    	for(int i = 1; i <= n; i++)
    	{
    		ll v = 0;
    		for(int j = 1; j <= 6; j++)
    		{
    			v *= base;
    			if(x & (1 << (j - 1))) v += a[i][j] + 1;
    		}
    		mp.insert(v);
    	}
    	return mp.calc();
    }
    
    int main()
    {
    	n = read(), k = read();
    	for(int i = 1; i <= n; i++) for(int j = 1; j <= 6; j++) a[i][j] = read();
    	c[0][0] = 1;
    	for(int i = 1; i <= 6; i++)
    	{
    		c[i][0] = 1;
    		for(int j = 1; j <= i; j++) c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
    	}
    	for(int i = 1; i < 64; i++) cnt[i] = cnt[i >> 1] + (i & 1);
    	long long ans = 0;
    	for(int i = 0; i < 64; i++)
    	{
    		if(cnt[i] >= k)
    		{
    			long long t = work(i);
    			t = t * c[cnt[i]][k];
    			if((cnt[i] - k) & 1) ans -= t;
    			else ans += t;
    		}
    	}
    	cout << ans << "
    ";
    	return 0;
    }
    
  • 相关阅读:
    laravel如何自定义一个路由文件
    RGAC-laravel权限管理
    导航栏下划线跟随
    php简单的判断用户登陆
    php判断文件上传的类型
    git 如何删除仓库中的文件
    laravle中config( )函数的使用
    [leetcode] Count and Say
    [leetcode] Sudoku Solver
    [leetcode] Search Insert Position
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/10679931.html
Copyright © 2011-2022 走看看