ds作业(hash)

来源:互联网 发布:centos 集成环境 编辑:程序博客网 时间:2024/06/06 08:53

(非常菜的hash姿势

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

9.1

题意:给定长度为 n(n<=1000000)的字符串,字符串仅由小写字母的前 m(m<=6)个字符组成,请你计算出共有多少长度为 k(k<=6)的不相同子串。

题解:把每个子串转换成6进制即可。

#include<cstdio>#include<cstring>const int N=1000005;char s[N];int a[N];int main() {int i,j,n,m,k,len,ans,tmp;scanf("%d%d%d%s",&n,&m,&k,s);len=strlen(s);ans=0;for(i=0;i+k-1<len;++i) {tmp=0;for(j=i;j<=i+k-1;++j) tmp=tmp*6+s[j]-'a'; if(a[tmp]==0) {a[tmp]=1;++ans;}}printf("%d\n",ans);return 0;}

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

9.2

题意:在n(n<=1000000)个字符串中查询m(m<=1000 且 m<=n)个字符串是否出现。每个字符串长度不超过5。

题解:把每个字符串转换成128进制。m次查询,排序n个关键字之后用二分查找。nlogm

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef __int64 ll;const int N=1000005;char s[10];ll a[N];int main() {int n,m,i,j,len,ans;ll tmp;scanf("%d%d",&n,&m);for(i=1;i<=n;++i) {scanf("%s",s);len=strlen(s);for(j=0;j<len;++j) a[i]=a[i]*128+s[j];}sort(a+1,a+1+n);ans=0;for(i=1;i<=m;++i) {scanf("%s",s);tmp=0;len=strlen(s);for(j=0;j<len;++j) tmp=tmp*128+s[j];if(*lower_bound(a+1,a+1+n,tmp)==tmp) ++ans;}printf("%d\n",ans);return 0;}


//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

9.3

题意:现在有一个简单的学生管理系统,要求实现以下几个功能:

1.向名单内添加学生,若名单内已有这个学生,则不操作。
2.删除名单内的某个学生,若此学生不在名单内,则输出“The student does not exist!”。
3.查询某学生是否存在。

每个学生名字长度不超过5。

题解:三种操作的关键都是要快速查询。因此使用散列把学生名字哈希到[0,100000)的区间上。这样每次操作的复杂度都是常数时间。

#include<cstdio>#include<string>#include<iostream>#include<vector>using namespace std;const int N=100000;vector<string> vec[N];int main() {int n,op,sz,i,len,pos,tmp;string s;scanf("%d",&n);while(n--) {cin>>op>>s;len=s.length();tmp=0;for(i=0;i<len;++i) tmp=(tmp*7+s[i])%N;sz=vec[tmp].size();pos=-1;for(i=0;i<sz;++i) {if(vec[tmp][i]==s) {pos=i;break;}}if(op==1) {if(pos==-1) {vec[tmp].push_back(s);}} else if(op==2) {if(pos==-1) {puts("The student does not exist!");} else {vec[tmp].erase(vec[tmp].begin()+pos);}} else {if(pos==-1) {puts("No");} else {puts("Yes");}}}return 0;}


//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

9.4

题意:给出一个方程 a*x1^2 + b*x2^2 + c*x3^2 + d*x4^2 = 0。

其中 a,b,c,d 的范围为[-10000,10000],且不为 0。
请问这个方程有多少种解(x1,x2,x3,x4 的取值范围是[-100,100]且不为 0)。

题解:

解法一:最后的解是[1,100]上的解的个数×16。那么只要枚举a,b,c的值,再看看d的值符不符合。
解法二:把c,d移项到方程另一边。那么对于每次方案,每边都可以处理成ll范围内的一个数。匹配一下就行了。

(其实很无聊

#include<cstdio>#include<cmath>typedef __int64 ll;int main() {int i,j,k,n,a,b,c,d,ans;ll tmp,t;scanf("%d",&n);while(n--) {scanf("%d%d%d%d",&a,&b,&c,&d);ans=0;for(i=1;i<=100;++i) {tmp=a*i*i;for(j=1;j<=100;++j) {tmp=(ll)a*i*i+b*j*j;for(k=1;k<=100;++k) {tmp=(ll)a*i*i+b*j*j+c*k*k;tmp=-tmp;if(tmp%d==0&&0<tmp/d&&tmp/d<=10000) {t=sqrt(tmp/d);if(t*t==tmp/d) ++ans;}}}}printf("%d\n",ans*16);}return 0;}




0 0
原创粉丝点击