hash的应用包括两种,一种是整数方面一种是字符串方面。
整数:
hdu1425:
水题,考虑将所有数据存到对应的hash数组,然后倒叙查找输出即可。考虑负数处理方式。
#include<bits/stdc++.h> using namespace std; int h[1000005]; //直接将数据存hash[i]对应的位置即可 int main(){ int m,n,k; while(scanf("%d%d",&m,&n)!=EOF){ memset(h,0,sizeof(h)); for(int i=0;i<m;i++){ scanf("%d",&k); h[k+500000]=1; } int num=1; for(int i=1000004;i>=0;i--){ if(h[i]==0)continue; if(h[i]==1){ if(num<n) cout<<i-500000<<" "; if(num==n) { cout<<i-500000<<endl; break; } num++; } } } return 0; }
hdu1496:
思路巧妙,考虑如果使用暴力,那么就要四层循环耗时很大,可以考虑计算a*i^2+b*j^2 和c*i^2+d*j^2 分别计算,最后判断是否和为0即可。
这里hash算法的用处是将第一部分计算的值存放到hash数组里,第二部计算结果直接查找hash中是否与其和为0的数即可。
这样算法的复杂度及改为2*n^2
需要注意的是:a,b,c,d不能全为正数或负数。参数正负情况结果相同,故有2^4种
#include<cstdio> #include<iostream> #include<cstring> using namespace std; //计算a*x1^2+b*x2^2+c*x3^2+d*x4^2=0 int pos[1000005];//正数结果存放位置 int neg[1000005];//负数结果存放位置 int main(){ int a,b,c,d; 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){ cout<<"0"<<endl; continue; } memset(pos,0,sizeof(pos)); memset(neg,0,sizeof(neg)); for(int i=1;i<=100;i++){ for(int j=1;j<=100;j++){ int num=a*i*i+b*j*j; if(num>=0)pos[num]++; else neg[-num]++; } } int sum=0; for(int i=1;i<=100;i++){ for(int j=1;j<=100;j++){ int num=c*i*i+d*j*j; if(num<=0)sum+=pos[-num]; else sum+=neg[num]; } } cout<<sum*16<<endl;//4个参数正负情况结果相同故有2^4种 } return 0; }
字符串:
hdu1228
题目很容易,只要将英文转为数字即可。难点在于如何输入,所以我们可以把+和=号作为标识符。
#include<cstdio> #include<iostream> #include<map> #include<string> using namespace std; /* 重点如何输入 */ map<string,int> ma; int main(){ ma["zero"]=0; ma["one"]=1; ma["two"]=2; ma["three"]=3; ma["four"]=4; ma["five"]=5; ma["six"]=6; ma["seven"]=7; ma["eight"]=8; ma["nine"]=9; int num=0; string in; while(1){ int a=0; while(cin>>in){ if(in=="+")break; a=a*10+ma[in]; } int b=0; while(cin>>in){ if(in=="=")break; b=b*10+ma[in]; } int sum=a+b; if(sum==0)break; cout<<a+b<<endl; } return 0; }