您的位置:首页 > 其它

ds作业(hash)

2016-12-27 22:07 239 查看
(非常菜的hash姿势

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

9.1

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

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

#include<cstdio>
#include<cstring>
const int N=1000005;
char s
;
int a
;
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
;
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
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: