哈希在ACM中题目的应用(不断收集中~)

1、HDU 1496

题意:输入abcd ,问满足方程 a*xi^2 + b*xj^2 =-1*( c*xk^2 + d*xt^2) 。 的解 xi(1,2,3,4) -->[-100 , 100]

思路:暴力做法就是四重循环, 用哈希,把等号左边的值套入哈希数组, 等号右边进行判断对应的哈希数组值就行,o(n^2);

还要注意一点,数组下标不能为负,因此生产下标时统统哈希为 t+1000000

code:

#include <iostream>
//#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
using namespace std;
int num[105];
int hash1[2000003];

int main()
{
    int a,b,c,d;
    for(int i=1; i<=100; i++)
    {
        num[i] = i*i;
    }
    while(scanf("%d%d%d%d",&a,&b,&c,&d) != EOF)
    {
        if(a>0 && b>0 &&c>0 &&d>0 || a<0 &&b<0 &&c<0 &&d<0)
        {
            printf("0\n");
            continue;
        }
        //cout<<"here"<<endl;
        memset(hash1,0,sizeof(hash1));
        for(int i=1; i<=100; i++)
        {
            for(int j=1; j<=100; j++)
            {
                hash1[a*num[i] + b*num[j] + 1000000]++;
            }
        }
        // cout<<"here1"<<endl;

        int ans = 0;

        for(int i=1; i<=100; i++)
        {
            for(int j=1; j<=100; j++)
            {    //cout<<"here2"<<endl;
               ans += hash1[1000000 + -( c*num[i] + d*num[j])];
            }
        }
        printf("%d\n",ans*16); // 题目是问 xi i=(1,2,3,4) 的解法。
        //ans是 x1^2 x2^2 == x3^2 x4^2 则 ans要乘上 2*2*2*2

    }

    return 0;
}

2、HDU-1425

题意:输入n个数,输出前m大的那几个数

思路:快排的话o(nlog(n)) , 若卡时间则不行,可用空间换时间。

具体做法:

while(n--)
{
    int t;
    scanf("%d",t);
    hash1[t+500000]++;
}

for(int i=500000*2;i>=0;i--)
{
    if(hash1[i] != 0)
    {
        m--;
        cout<<i-500000<<endl;
        if(m ==0)
        break;
    }
}

3、HDU-1800

题意:输入n个字符串,问相同的字符串的个数

思路:map飘过,正解是字符串哈希。str[0] * base^n-1 + str[1] * base^n-2 + .... + str[n-1]

类比数字1234  = 1*1000+2*100+3*10+4

这里拓展下0x3F3F3F3F 和0x7FFFFFFF

0X7FFFFFFF 是INT_MAX ,再加1 就溢出成负数,因此不用于运算,不过longlong的取模要用这个

0x3f3f3f3f 达到了1e9 ,作为inf 运算不会溢出为负数。

#include <iostream>
//#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <map>
#include <cmath>
#include <algorithm>


using namespace std;
typedef long long ll;
char st[50];
int Hash[3005];

int hashit(char *st)
{
    ll base = 131;
    ll tmp = 0;
    while(*st == '0') // 前导0去掉
        st++;
    while(*st)
    {
        tmp = tmp*base + (*st++);
    }
    return (tmp & 0x7FFFFFFF); // 对INT最大值取模
}

int main()
{
    int n;
    while(scanf("%d",&n) !=EOF)
    {
        
        for(int i=0; i<n; i++)
        {
            scanf("%s",st);
            Hash[i] = hashit(st);
        }

        sort(Hash,Hash+n);
        int temp=1;
        int ans = 1;
        for(int i=1; i<n; i++) //ans即为 相等的数的最大值
        {
            if(Hash[i]==Hash[i-1])
            {
                temp++;
                if(temp>ans)
                    ans=temp;
            }
            else
                temp=1;
        }
        printf("%d\n",ans);
    }
    
    
    return 0;
}
//很不错的字符串哈希函数
unsigned int ELFhash(char *str)
{
	unsigned int hash=0;
	unsigned int x=0;
	while(*str)
	{
		hash=(hash<<4)+*str;     //1
		if((x=hash & 0xf0000000)!=0)         //2
		{
			hash^=(x>>24);   //影响5-8位,杂糅一次   3
			hash&=~x;   //清空高四位    4
		}
		str++;   //5
	}
	return (hash & 0x7fffffff);    //6 
}

猜你喜欢

转载自blog.csdn.net/qq_37591656/article/details/81221630