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\n");
		}
		else printf("%d\n", 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\n", 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\n", 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\n", Max);
		for (int i = 0; i<B - 1; i++){
			for (int j = p[i]; j<p[i + 1]; j++) printf("%c", j + ‘A‘);
			printf("\n");
		}
		for (int i = p[B - 1]; i<L; i++) printf("%c", i + ‘A‘);
		if (p[B - 1] <= L - 1) printf("\n");
	}
	return 0;
}

  

时间: 2024-10-13 22:59:21

Hash小结的相关文章

MySQL中Btree和Hash的局限小结

在索引中,Btree索引和Hash索引的局限性,在这里粗略罗列一下 1 Btree局限 B-树中的节点都是顺序存储的,所以可以利用索引进行查找(找某些值),也可以对查询结果进行ORDER BY(注意ORDER BY后面建议跟主键)1 查询必须从索引最左边的列开始2 不能跳过某一索引列3 存储引擎不能使用索引中范围条件右边的列 2 Hash的局限 1 仅仅能满足"=","IN"和"<=>"查询,不能使用范围查询2 无法被用来避免数据的排

Redis系列-存储篇hash主要操作函数小结

hash是一些列key value(field value)的映射表.常常用其存储一些对象实例.相对于把一个对象的各个字段存储为string,存储为hash会占用更少的内存.为什么会更省内存呢?需要搞清楚两个配置(hash-max-zipmap-entries和hash-max-zipmap-value)的含义,配置的详细介绍,我打算放在最后的配置优化环节讲. 1)新增 a)hset 语法:hset key field value 解释:设置hash表key中的field的值.如果hash表不存

小结:hash

概要: 判重的时候可以用手写hash,也可以用stl中的map,手写hash的好处是快,解决冲突的方案较好,map慢.但是手写hash要求的空间高,而且有时处理得不好的话会wa. 注意及技巧: 注意的是,hash的函数一定要写好,但是写好又爆空间.一般采用元素个数作为基数然后乘上递增的这个基数的幂作为权重,mod的时候要注意处理冲突,我们可以直接用到达的下标一直向后找个空的位置放下即可.例题:[COGS & USACO Training]710. 命名那个数字(hash+水题+dfs),[wik

oracle 表连接 - hash join 哈希连接

一. hash 连接(哈希连接)原理 指的是两个表连接时, 先利用两表中记录较少的表在内存中建立 hash 表, 然后扫描记录较多的表并探測 hash 表, 找出与 hash 表相匹配的行来得到结果集的表连接方法. 哈希连接仅仅能用于等值连接条件(=). 如果以下的 sql 语句中表 T1 和 T2 的连接方式是哈希连接, T1 是驱动表 select * from T1, T2 where T1.id = T2.id and T1.name = 'David'; oracle 运行过程例如以下

java 小结3 hashcode和equals I/o问题

我需要把星期天看的一些东西记录下来,要不然会忘记. hashCode.equals: 1)每个java对象都有hashCode和equals方法. java的终极类是object类,那么object类是如何来标注自己呢,就是object这个类是如何来区分对方.就是使用它们的hashcode和equals来推断. (hashcode是通过hash算法实现的) 2)JVM每new一个object,都会讲Object丢到一个Hash(哈希表)里去,这样下次比较或者获取这个对象的时候就可以根据对象的ha

python提供了一个进行hash加密的模块:hashlib

python提供了一个进行hash加密的模块:hashlib下面主要记录下其中的md5加密方式 import hashlib data1 = 'sada' #####字母和数字 m = hashlib.md5(data1.encode('utf-8')) print(m.hexdigest()) data='我是' #####中文 b = hashlib.md5(data.encode('gb2312')) print(b.hexdigest()) def md5(s): ####这是一个MD5

[转载] Java集合框架之小结

转载自http://jiangzhengjun.iteye.com/blog/553191 1.Java容器类库的简化图,下面是集合类库更加完备的图.包括抽象类和遗留构件(不包括Queue的实现): 2.ArrayList初始化时不可指定容量,如果以new ArrayList()方式创建时,初始容量为10个:如果以new ArrayList(Collection c)初始化时,容量为c.size()*1.1,即增加10%的容量:当向ArrayList中添加一个元素时,先进行容器的容量调整,如果容

java集合框架小结(进阶版)之HashMap篇

基本概念: Hash(哈希):hash一般也译作“散列”.事实上,就是一个函数,用于直接定址.将数据元素的关键字key作为变量,通过哈希函数,计算生成该元素的存储地址. 冲突:函数是可以多对一的.即:多个自变量可以映射到同一函数值.一般而言,不同的key的hash值是不同的.在往hash表中映射的时候,不同的hash值可能映射到同一存储地址,这种情况被称为冲突. 解决冲突的方法: 1. 链表法:将冲突的各个元素用一个一维数组来维护.(java源码实现) 2. 开发寻址法:具体的有线性探测法.二次

java集合框架小结(进阶版)之HashSet篇

建议先看下:java集合框架小结(进阶版)之HashMap篇 基本概念: hashSet: 根据java集合框架小结(初级版)图示,HashSet是AbstractSet的一个子类,是基于Hash算法的Set接口的实现,顾名思义.允许添加null. --------------------------------------↑ 以上都是扯淡 ↑,↓ HashSet完全是在挂羊头卖狗肉 ↓------------------------------------------- 何谓挂羊头卖狗肉?大家