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)的区间上。这样每次操作的复杂度都是常数时间。
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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;
}
相关文章推荐
- express + node.js 入门(4)数据读取接口
- python 细节上的一些笔记
- 742 C. Arpa's loud Owf and Mehrdad's evil plan codeforces
- MySQL入门教程
- 程序员面试
- Java设计模式一
- UVALive7220
- C库函数的手册
- Web-Nginx配置
- 用JAVA写查询一个字符串中是否包含另外一个字符串以及出现的次数
- 深入实践Spring boot读书笔记之Spring与Spring boot的区别
- 银行收银系统(C#)
- linux不能启动的修复技巧
- Android热修复技术选型——三大流派解析
- 【Map使用】遍历Map集合案例keySet()和 entrySet()
- Programming Exercise 5: Regularized Linear Regression and Bias v.s. Variance Machine Learning
- 基础入门_Python-模块和包.深入Celery之Beat触发定时/周期性任务?
- Linux内核中断机制(四):中断处理下
- Django part01
- linux之路由知识之ip route 命令中的疑惑