2021年7月16日
哈希第一弹
题目传送门–B1033旧键盘打字
没错没错,这是2/5通过率版本,第一版3/5,改了之后不仅还是超时,结果正确率又降了,嘤嘤嘤~~
//1033
#include<bits/stdc++.h>
using namespace std;
char test[200000];
char bad[100];
bool flag=false;
map<char,int>mp;
int main(){
scanf("%s%s",bad,test);
for(int i=0;i<strlen(bad);i++){
if(bad[i]=='-'||bad[i]=='+'||bad[i]=='.'||bad[i]==','){
flag=true;//大写失灵
}
mp[bad[i]]=true;
if(bad[i]<='Z'&&bad[i]>='A'){
mp[bad[i]-'A'+'a']=true;
}
}
int count=0;
for(int i=0;i<strlen(test);i++){
if(test[i]<='Z'&&test[i]>='A'&&flag)continue;
if(mp[test[i]])continue;
count++;
printf("%c",test[i]);
}
printf("\n");
return 0;
}
然后,如果是熟悉了string类的自带的一些很”妙“的操作就真的很妙了!
参考了柳神的代码
#include<iostream>
#include<cctype>
using namespace std;
int main(){
string bad,test;
getline(cin,bad);
getline(cin,test);
for(int i=0;i<test.length();i++){
if(bad.find(toupper(test[i]))!=string::npos)continue;//是一定打不出来的
if(isupper(test[i])&&bad.find('+')!=string::npos )continue;//错误原因,题意的理解,只有+代表上档键
cout<<test[i];
}
cout<<"\n";
return 0;
}
终于跑通了,之前主要是题意理解错了,上档只有+,然后输入的测试中+自己本身也算一个字符;超时的原因大概是自己造的‘轮子’效率没有string自带的函数高;
**string::npos
isupper(str)😗*判断是否为大写
**toupper(str):**改写成大写
哈希第二弹
题目传送门–甲级1092到底买不买
这一题涉及到的是哈希,emm讲真我没看出来
不过因为C++很多函数库不熟,所以自己就着上一题柳神的思路查了一下string 的一些奇奇怪怪基础用法
一次通过太感动啦
//1092甲级
#include<iostream>
#include<cctype>
using namespace std;
//如果符合,则需要输出额外需要买的
//如果不符合,需要输出还缺的个数
string shop;
string want;
int main(){
getline(cin,shop);
getline(cin,want);
int num=want.length();//需要的
int sum=num;
for(int i=0;i<shop.length();i++){
if(want.find(shop[i])!=string::npos){
num--;
want.erase(want.begin()+want.find(shop[i]));
}
}
if(num<=0){
cout<<"Yes "<<shop.length()-sum<<endl;
}else{
cout<<"No "<<num<<endl;
}
return 0;
}
**string.erase()**删除指定位置的字符
**string.find()**查找特定字符,返回他在string中的位置
它有具体几种用法Str的find与erase函数
哈希第三弹
一开始以为是输出所有最大值字母来着,排序题最近可能练的多了一点嘿嘿~
这题很基础,不过又掌握了**tolower()**的用法,算是对string类型进一步熟悉熟悉😀
//1042字符统计
#include<bits/stdc++.h>
using namespace std;
string a;
//统计英文字母,频率
struct node{
char ch='?';
int time=0;
}num[26];
bool cmp(node a,node b){
if(a.time!=b.time)return a.time>b.time;
else return a.ch<b.ch;
}
int main(){
getline(cin,a);
for(int i=0;i<a.length();i++){
if(a[i]<='z'&&a[i]>='a'){
num[a[i]-'a'].time++;
num[a[i]-'a'].ch=tolower(a[i]);
}else if(a[i]<='Z'&&a[i]>='A'){
num[a[i]-'A'].time++;
num[a[i]-'A'].ch=tolower(a[i]);//大写转小写
}
}
sort(num,num+26,cmp);
int maxn=num[0].time;
for(int i=0;i<26;i++){
if(num[i].time==maxn){
if(i==0)
printf("%c %d",num[i].ch,num[i].time);
else
printf(" %c %d",num[i].ch,num[i].time);
break;
}
}
printf("\n");
return 0;
}
哈希第三弹
1043乙组输出PATest
这题好像没有什么坑🕳,方法也比较多,当然我的方法用了map映射,其实因为只有6个字母,其实也没有必要,代码显得相当冗余臃肿啦
//1043
#include<bits/stdc++.h>
using namespace std;
//打印PATest
string a;
string c="PATest";
map<char,int>mp;
int main(){
getline(cin,a);
mp['P']=0;mp['A']=0;mp['T']=0;
mp['e']=0;mp['s']=0;mp['t']=0;
int sum=0;
for(int i=0;i<a.length();i++){
if(a[i]=='P'||a[i]=='A'||a[i]=='T'||a[i]=='e'||a[i]=='s'||a[i]=='t'){
mp[a[i]]++;
sum++;
}
}
while(sum){
for(int i=0;i<6;i++){
if(mp[c[i]]){
mp[c[i]]--;
printf("%c",c[i]);
sum--;
}
if(sum==0)break;
}
}
return 0;
}
哈希第四弹
B1047团体编程赛
这是一个虽然AC 但是很明显有很大漏洞的代码——单纯的使用了线性映射,在数据集小的测试样例上OK但是可以预见,测试数据稍微残酷一点,这份代码的表现会很糟糕QAQ
不过搜了一下……好像也没有看到压缩空间的解法……呜呜呜
//1047
#include<bits/stdc++.h>
using namespace std;
struct node{
int team;
int id;
int score;
};
struct Team{
int id;
int score=0;
};
int n;
Team b[20000];
bool cmp(Team a,Team b){
return a.score>b.score;
}
int main(){
scanf("%d",&n);
int team,id,score;
for(int i=0;i<n;i++){
scanf("%d-%d %d",&team,&id,&score);
b[team].id=team;
b[team].score+=score;
}
sort(b,b+10000,cmp);
printf("%d %d",b[0].id,b[0].score);
return 0;
}
哈希第五弹
A1041 Be Unique
这题不难,关键就是……开数组开小了,10000和100000的区别,下次要细心一点呀
关键是,报错的时候说“答案错误”,应该是“段错误”昂
//甲级1041:哈希
#include<bits/stdc++.h>
using namespace std;
int n;
int num[101100];
int ccount[101100];
int main() {
scanf("%d",&n);
memset(ccount,0,sizeof(ccount));
for(int i=0;i<n;i++){
scanf("%d",&num[i]);//选择的数据
ccount[num[i]]++;
}
for(int i=0;i<n;i++){
//debug
//printf("数字为:%d 次数为: %d\n",num[i],ccount[num[i]]);
if(ccount[num[i]]==1){
printf("%d",num[i]);
return 0;
}
}
printf("None");
return 0;
}
哈希第六弹
A1050 String Subtraction
这题也是,没有什么难度,规定了时间的话,肯定不能两个字符串轮流遍历啦,考虑用哈希~~(其实是因为俺在集中练习哈希,感觉可能没有这个背景的话,我也是暴力超时的那个嘿嘿)~~
ac如下:
果然按着算法笔记的顺序来练习就不会轻易被劝退啦
//1050
#include<bits/stdc++.h>
using namespace std;
//快速输出两个字符串相减的结果
map<char,int>mp;
string a,b;
int main(){
getline(cin,a);
getline(cin,b);
for(int i=0;i<b.length();i++ ){
if(!mp[b[i]]){
mp[b[i]]=1;
}else{
mp[b[i]]++;
}
}
for(int i=0;i<a.length();i++){
if(!mp[a[i]]){
printf("%c",a[i]);
continue;
}
}
return 0;
}
哈希第七弹
没想到这么快就快结束哈希啦(排序那边还欠了一点收尾呜呜呜~~~)
B1005继续(3n+1)猜想
基础题,但是没想到PTA的数据也有问题,题目中明明给的限制是不超过100,实际得100000才没有“段错误”的报错,嗨呀,万望仔细
//1005
#include<bits/stdc++.h>
using namespace std;
/*
对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;
如果它是奇数,那么把 (3n+1) 砍掉一半。
这样一直反复砍下去,最后一定在某一步得到 n=1。
*/
int n;
int num[10900];
int mp[50000]={0};//某一个数字,是否可以由其他数字得到
void f(int n){
if(mp[n]){
//第一个数字已经被标记过了
mp[n]++;
return;
}else{
mp[n]=1;
}
while(n!=1){
// printf("%d\n",n);
if(n%2==0){
n/=2;
}else{
n=(3*n+1)/2;
}
if(!mp[n]){
mp[n]=1;//第一个数字
}else{
mp[n]++;
}
}
return ;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&num[i]);
}
for(int i=0;i<n;i++){
f(num[i]);
}
bool flag=false;
//printf("chulai");
sort(num,num+n);
for(int i=n-1;i>=0;i--){
if(mp[num[i]]&&mp[num[i]]==1){
if(!flag)
printf("%d",num[i]);
else
printf(" %d",num[i]);
flag=true;
}
}
return 0;
}
哈希第八弹
A1048 Find Coins
其实完全没有感觉到是甲级的题目危险发言
也没有感觉到是散列的题目,感觉不是很难✌
//1048甲级
#include<bits/stdc++.h>
using namespace std;
int coin[200000];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&coin[i]);
}
sort(coin,coin+n);
int amin,amax;
int i=0;
amin=coin[i];
amax=coin[--n];
while(i<n){
if(amin+amax==m){
printf("%d %d",amin,amax);
return 0;
}else if(amin+amax>m){
amax=coin[--n];
}else{
amin=coin[++i];
}
}
printf("No Solution");
return 0;
}
就酱,哈希就暂告一段落叭~~~~