zoukankan      html  css  js  c++  java
  • Hash小结

    Poj1480Eqs

    a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0 ->a1x13+ a2x23+ a3x3=-(a4x43+ a5x53  

    问有多少个满足等式的非零x1,x2,x3,x4,x5组。)

    中途相遇法,枚举x1,x2,x3得到左边式子的值插入hash表,然后枚举x4,x5找到对应的值就行了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <bitset>
    #include <queue>
    #include <stack>
    #include <string>
    #include <iostream>
    #include <cmath>
    #include <climits>
    typedef long long LL ;
    using namespace std;
    
    const int maxn = 1e6 + 7;
    const int Hash = 1e5 + 7;
    
    struct HashMap
    {
    	int head[Hash + 10]; int size; int next[maxn*2]; int val[maxn*2]; int cnt[maxn*2];
    	void init()
    	{
    		size = 0;  memset(head, -1, sizeof(head));
    	}
    	int ask(int x)
    	{
    		int k = (x%Hash + Hash) % Hash;
    		for (int i = head[k]; i != -1; i = next[i]){
    			if (val[i] == x) return cnt[i];
    		}
    		return 0;
    	}
    	void insert(int x)
    	{
    		int k = (x%Hash + Hash) % Hash;
    		for (int i = head[k]; i != -1; i = next[i]){
    			if (val[i] == x){
    				cnt[i] ++; return;
    			}
    		}
    		val[size] = x; cnt[size] = 1; next[size] = head[k];
    		head[k] = size++;
    		return;
    	}
    }m;
    
    int gao(int i)
    {
    	return i*i*i;
    }
    
    int main()
    {
    	int a, b, c, d, e;
    	while (cin>>a>>b>>c>>d>>e){
    		int ans = 0;
    		m.init();
    		for (int i = -50; i <= 50; i++)if (i){
    			for (int j = -50; j <= 50; j++)if (j){
    				for (int k = -50; k <= 50; k++)if (k){
    					int t = a*gao(i) + b*gao(j)+c*gao(k);
    					m.insert(t);
    				}
    			}
    		}
    		for (int i = -50; i <= 50; i++)if (i){
    			for (int j = -50; j <= 50; j++)if (j){
    				int t = d*gao(i) + e*gao(j);
    				ans += m.ask(-t);
    			}
    		}
    		cout << ans << endl;
    	}
    	return 0;
    }
    

     Poj2549  Sumsets

      题意:Given S, a set of integers, find the largest d such that a + b + c = d where a, b, c, and d are distinct elements of S.

     还是用中途相遇法搞下就好了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <bitset>
    #include <queue>
    #include <stack>
    #include <string>
    #include <iostream>
    #include <cmath>
    #include <climits>
    typedef long long LL;
    using namespace std;
    
    const int Hash = 1e6 + 10;
    const int maxn = 1e6 + 10;
    
    
    struct HashMap
    {
    	int head[Hash + 10]; int size; int next[maxn + 10]; int val[maxn + 10]; int a[maxn + 10], b[maxn + 10];
    	void init()
    	{
    		size = 0; memset(head, -1, sizeof(head));
    	}
    	void insert(int t, int x, int y)
    	{
    		int k = (t%Hash + Hash) % Hash;
    		for (int i = head[k]; i != -1; i = next[i]){
    			if (val[i] == t){
    				if (a[i] == x&&b[i] == y) return;
    			}
    		}
    		val[size] = t; next[size] = head[k]; a[size] = x; b[size] = y; head[k] = size++;
    	}
    	int ask(int t, int x, int y)
    	{
    		int k = (t%Hash + Hash) % Hash;
    		for (int i = head[k]; i != -1; i = next[i]){
    			if (val[i] == t){
    				if (a[i] != x&&b[i] != x&&a[i] != y&&b[i] != y) return 1;
    			}
    		}
    		return 0;
    	}
    
    }m;
    int cmp(const int &a, const int &b)
    {
    	return a > b;
    }
    int a[1111];
    int main()
    {
    	int n;
    	while (scanf("%d", &n) != EOF&&n){
    		for (int i = 0; i < n; i++){
    			scanf("%d", &a[i]);
    		}
    		m.init();
    		sort(a, a + n, cmp);
    		for (int i = 0; i < n; i++){
    			for (int j = 0; j < n; j++){
    				if (i == j)continue;
    				m.insert(a[i] + a[j], i, j);
    			}
    		}
    		int flag = 1; int pos;
    		for (int i = 0; flag&&i < n; i++){
    			for (int j = 0; flag&&j < n; j++){
    				if (i == j) continue;
    				int t = m.ask(a[i] - a[j], i, j);
    				if (t){
    					flag = 0; pos = i; break;
    				}
    			}
    		}
    		if (flag){
    			printf("no solution
    ");
    		}
    		else printf("%d
    ", a[pos]);
    	}
    	return 0;
    }
    

    Poj3274 Gold Balanced Lineup

    就是给出一些数,找到最大的连续区间使得区间内对应的二进制位上的1的个数相等。

    若区间l,r满足条件,sum[i][j] 表示前i个数的第j位上的1的个数和。

    sum[r][1] - sum[l][1] = sum[r][2] - sum[l][2].....->sum[r][1] - sum[r][2] = sum[l][1] - sum[l][2];

    每一位都减去某位的值过以后,若是存在l,r区间满足条件则处理过后的对应位的值相等,此时用hash搞下。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <bitset>
    #include <queue>
    #include <stack>
    #include <string>
    #include <iostream>
    #include <cmath>
    #include <climits>
    typedef long long LL;
    using namespace std;
    
    const int Hash = 1e6 + 10;
    const int maxn = 2e5 + 10;
    int k;
    struct HashMap
    {
    	int head[Hash + 10]; int next[maxn + 10]; int val[maxn + 10]; int ans[maxn + 10][31];
    	int pos[maxn + 10];
    	int size;
    	void init()
    	{
    		size = 0; memset(head, -1, sizeof(head));
    	}
    	int ask(int a[])
    	{
    		int t = 0;
    		for (int i = 0; i < k; i++) t += a[i];
    		int gg = (t%Hash + Hash) % Hash;
    		for (int i = head[gg]; i != -1; i = next[i]){
    			if (val[i] == t){
    				int flag = 0;
    				for (int j = 0; j < k; j++) {
    					if (ans[i][j] != a[j]) {
    						flag = 1; break;
    					}
    				}
    				if (flag == 0) return pos[i];
    			}
    		}
    		return -2;
    	}
    	void insert(int a[], int p)
    	{
    		int t = 0;
    		for (int i = 0; i < k; i++) t += a[i];
    		int gg = (t%Hash + Hash) % Hash;;
    		for (int i = head[gg]; i != -1; i = next[i]){
    			if (val[i] == t){
    				int flag = 0;
    				for (int j = 0; j < k; j++){
    					if (ans[i][j] != a[j]){
    						flag = 1; break;
    					}
    				}
    				if (flag == 0) return;
    			}
    		}
    		val[size] = t; next[size] = head[gg];
    		pos[size] = p;
    		for (int i = 0; i < k; i++) ans[size][i] = a[i];
    		head[gg] = size++;
    	}
    }m;
    
    int cnt[100];
    
    void gao(int a)
    {
    	int len = 0;
    	while (a){
    		cnt[len++] += a % 2;
    		a >>= 1;
    	}
    }
    
    int main()
    {
    	int n; int a;
    	while (scanf("%d%d", &n, &k) != EOF){
    		int Max = 0;
    		memset(cnt, 0, sizeof(cnt));
    		m.init(); m.insert(cnt, -1);
    		for (int i = 0; i < n; i++){
    			scanf("%d", &a); gao(a);
    			for (int j = k - 1; j >= 0; j--) cnt[j] -= cnt[0];
    			int t = m.ask(cnt);
    			if (t != -2) Max = max(Max, i - t);
    			m.insert(cnt, i);
    		}
    		printf("%d
    ", Max);
    	}
    	return 0;
    }
    

    Hdu3333 Turing Tree

    区间长度3e4 ,1e5个询问。

    给出区间,求区间内不同元素和的个数。

    开始用莫队算法多了sqrt(n)的复杂度,超时了(或许姿势写戳了).后来搜了下题解,发现按照查询的右端点排序,然后线段树边插入,边查询就好了。

    到第i个元素的时候,只保留i这个大小的数最后一次出现的位置,前面出现过的位置上的数置0。由于是按右端点排序,在到达第k条询问的右端点的时候,保证到了当前位置区间内所有重复的数只有一个。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <bitset>
    #include <queue>
    #include <stack>
    #include <string>
    #include <iostream>
    #include <cmath>
    #include <climits>
    typedef long long LL;
    using namespace std;
    
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    
    const LL maxn = 33333;
    LL sum[maxn << 2];
    LL last[maxn];
    LL n;
    LL a[maxn];
    LL b[maxn];
    void build(LL l, LL r, LL rt)
    {
    	sum[rt] = 0;
    	if (l == r) return;
    	LL mid = (l + r) >> 1;
    	build(lson); build(rson);
    }
    
    void up(LL rt)
    {
    	sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    }
    
    void update(LL pos, LL add, LL l, LL r, LL rt)
    {
    	if (l == r){
    		sum[rt] = add; return;
    	}
    	LL mid = (l + r) >> 1;
    	if (pos <= mid) update(pos, add, lson);
    	else update(pos, add, rson);
    	up(rt);
    }
    
    LL ask(LL L, LL R, LL l, LL r, LL rt)
    {
    	if (L <= l&&r <= R) return sum[rt];
    	LL mid = (l + r) >> 1;
    	LL ans = 0;
    	if (L <= mid) ans += ask(L, R, lson);
    	if (R>mid) ans += ask(L, R, rson);
    	return ans;
    }
    
    void init()
    {
    	vector<LL> q1;
    	for (LL i = 0; i < n; i++) q1.push_back(a[i]);
    	sort(q1.begin(), q1.end());
    	q1.erase(unique(q1.begin(), q1.end()), q1.end());
    	for (LL i = 0; i < n; i++) b[i] = lower_bound(q1.begin(), q1.end(), a[i]) - q1.begin();
    }
    struct Node
    {
    	LL l; LL r; LL id;
    }node[111111];
    
    LL cmp(const Node &a1, const Node &b1)
    {
    	return a1.r < b1.r;
    }
    LL ans[111111];
    
    int main()
    {
    	LL T;
    	cin >> T;
    	LL q;
    	while (T--){
    		cin >> n;
    		build(0, n - 1, 1);
    		for (LL i = 0; i < n; i++){
    			scanf("%I64d", &a[i]);
    		}
    		init();
    		cin >> q;
    		for (LL i = 0; i < q; i++){
    			scanf("%I64d%I64d", &node[i].l, &node[i].r); node[i].l -= 1; node[i].r -= 1;
    			node[i].id = i;
    		}
    		memset(last, -1, sizeof(last));
    		sort(node, node + q, cmp);
    		LL pos = 0;
    		for (LL i = 0; i < q; i++){
    			while (pos <= node[i].r){
    				LL t = last[b[pos]];
    				if (t == -1){
    					update(pos, a[pos], 0, n - 1, 1);
    					last[b[pos]] = pos;
    				}
    				else{
    					update(last[b[pos]], 0, 0, n - 1, 1);
    					update(pos, a[pos], 0, n - 1, 1);
    					last[b[pos]] = pos;
    				}
    				pos++;
    			}
    			ans[node[i].id] = ask(node[i].l, node[i].r, 0, n - 1, 1);
    		}
    		for (LL i = 0; i < q; i++){
    			printf("%I64d
    ", ans[i]);
    		}
    	}
    	return 0;
    }
    

    Poj3188 

    题意:把L个字母按顺序分成连续的B份,变成手机按键,然后给出字典,问这些字典用手机按键去按,有多少个单词不存在冲突。

    暴力枚举划分方式,然后hash去判断冲突。在弄的时候因为用了map,超时了,调了好久。。写的很戳

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <bitset>
    #include <queue>
    #include <stack>
    #include <string>
    #include <iostream>
    #include <cmath>
    #include <climits>
    typedef long long LL;
    using namespace std;
    
    const int Hash = 128;
    const int maxn = 1e6;
    
    int askval(char *s)
    {
    	int k = 0;
    	while (*s) k = (*s++) + (k << 6) + (k << 16) - k;
    	return (k & 0x7fffffff);
    }
    
    int B, L, n;
    
    struct HashMap
    {
    	int size; int head[Hash + 10]; int val[maxn + 10]; int next[maxn + 10]; char s[maxn][14];
    	int cnt[maxn + 10];
    	void init()
    	{
    		size = 0; memset(head, -1, sizeof(head));
    	}
    	int ask(char *s1)
    	{
    		int k = askval(s1);
    		int t = (k%Hash + Hash) % Hash;
    		for (int i = head[t]; i != -1; i = next[i]){
    			if (val[i] == k){
    				if (strcmp(s1, s[i]) == 0) return cnt[i];
    			}
    		}
    		return 0;
    	}
    	void insert(char *s1)
    	{
    		int k = askval(s1);
    		int t = (k%Hash + Hash) % Hash;
    		for (int i = head[t]; i != -1; i = next[i]){
    			if (val[i] == k) if (strcmp(s1, s[i]) == 0){
    				cnt[i]++; return;
    			}
    		}
    		val[size] = k; next[size] = head[t]; strcpy(s[size], s1); cnt[size] = 1;
    		head[t] = size++;
    	}
    
    }T;
    
    char str[1111][12];
    int a[100];
    int Max;
    int p[100];
    int m[30];
    void gao(int pos, int sum)
    {
    	if (sum == B){
    		T.init();
    		memset(m, 0, sizeof(m));
    		for (int i = 0; i<B - 1; i++){
    			for (int j = a[i]; j<a[i + 1]; j++) m[j] = i;
    		}
    		for (int i = a[B - 1]; i<L; i++) m[i] = B - 1;
    		int ans = 0;
    		for (int i = 0; i<n; i++){
    			char s1[14]; strcpy(s1, str[i]);
    			int len = strlen(s1);
    			for (int j = 0; j<len; j++) s1[j] = m[s1[j] - 'A'] + 'A';
    			int t = T.ask(s1);
    			if (!t) T.insert(s1), ans++;
    			if (t == 1){
    				ans--; T.insert(s1);
    			}
    		}
    		if (ans>Max){
    			Max = ans; for (int i = 0; i<B; i++) p[i] = a[i];
    		}
    		return;
    	}
    	if (sum == 0){
    		a[sum] = 0; gao(0, sum + 1);
    	}
    	else
    	for (int i = L - B + sum; i>pos; i--){
    		a[sum] = i;
    		gao(i, sum + 1);
    	}
    }
    
    
    int main()
    {
    	while (scanf("%d%d", &B, &L) != EOF){
    		scanf("%d", &n);
    		a[0] = -1; p[0] = -1;
    		for (int i = 0; i < n; i++){
    			scanf("%s", str[i]);
    		}
    		Max = -1;
    		gao(0, 0);
    		printf("%d
    ", Max);
    		for (int i = 0; i<B - 1; i++){
    			for (int j = p[i]; j<p[i + 1]; j++) printf("%c", j + 'A');
    			printf("
    ");
    		}
    		for (int i = p[B - 1]; i<L; i++) printf("%c", i + 'A');
    		if (p[B - 1] <= L - 1) printf("
    ");
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    linux运维学习
    2017年阿里巴巴三面经验
    Spring Boot:在Spring Boot中使用Mysql和JPA
    meshroom和alicevision在Ubuntu16上的安装过程
    ubuntu rm -rf ntfs 硬盘恢复
    python 脚本内部修改 LD_LIBRARY_PATH
    python uml 图
    tlmgr 相关
    ubuntu 安装 clangd 10.0.0
    zsh 快捷键
  • 原文地址:https://www.cnblogs.com/yigexigua/p/4340099.html
Copyright © 2011-2022 走看看