夜色已经很晚了,所以我长话短说
1.表单
链接:https://ac.nowcoder.com/acm/contest/917/C
来源:牛客网
输入描述:
第一行两个整数n,Q
后n行每行一个字符串
后Q行每行代表一个操作:
一操作:1 s
二操作:2
输出描述:
对于每个二操作,进行回答。
这道题之前觉得4 4 这种输入也没啥用,结果开始编程直接没编进去,打算结束的时候往里加,结果忘了,由此带来的退出循环问题耗时耗力影响了解题进度。下次首先1.把输入的格式先写好2.尽量看清能给的条件,团结一切可以团结的力量。
莫名其妙flag每次结尾置0导致报错
cin换成scanf提高正确率
以上两点都是编译器自己sb
对map的循环不能放在循环里,会超时,这个值得注意
下面放出我期待已久的map以及迭代器的用法,真的是太方便了,鸟枪换炮感觉就是不一样!!开森(/≧▽≦)/
map<string,int> word_count; map<string,int>::iterator iter; //输入字符串进map for(int i=0;i<a1;i++) { cin>>word; ++word_count[word]; } //对map进行遍历,并对数值进行操作 for(iter = word_count.begin(); iter != word_count.end(); iter++) { res+=(iter->second-1); iter->second=1; }
这道题在思路上有一个改进点:
核心本题是求,字符重复的次数,我一直觉得得把map中的次数统计部分,数数,开始还为此发愁,后来直接遍历的时候每个减1,就是重复次数了
但,其实还有更好方法。用
if(flag==1) { cin>>word; //if括号里面的内容,运用了map的属性,如果这个词之前没有出现过,查无此人,则一定会 //是false,这种情况就说明出现了重复,用一个单独的变量统计重复的次数,只在这个时候 //++即可减轻了计算负担 if(word_count[word]) res++; else word_count[word]=1; flag=0; }
下面放出我的解法:
#include<iostream> #include<math.h> #include<map> #include <string> #include<stdio.h> #include <cstdlib> using namespace std; int main() { map<string,int> word_count; map<string,int>::iterator iter; string word; int flag=-1; int res=0; int a1,a2; //scanf("%d %d",&a1,&a2); cin>>a1>>a2; for(int i=0;i<a1;i++) { cin>>word; ++word_count[word]; } for(iter = word_count.begin(); iter != word_count.end(); iter++) { res+=(iter->second-1); iter->second=1; } for(int i=0;i<a2;i++) { //cout<<"flag:"<<flag<<endl; scanf("%d",&flag); //cout<<"flag1:"<<flag<<endl; //cin>>flag; if(flag==1) { cin>>word; if(word_count[word]) res++; else word_count[word]=1; } else { cout<<res<<endl; res=0; } } return 0; }
真正大佬的代码,看看什么叫信达雅
//膜大佬 #include<bits/stdc++.h> using namespace std; int n,q,res; map<string,int> mp; int main() { scanf("%d %d",&n,&q); while(n--) { string str; cin>>str; if(mp[str]) res++; else mp[str]=1; } while(q--) { int op; scanf("%d",&op); if(op==1) { string str; cin>>str; if(mp[str]) res++; else mp[str]=1; } else { printf("%d\n",res); res=0; } } return 0; }
2.pow慎用
尤其是先开完方再平方就容易有问题
int main() { int n=100; //如果是double的,结果还可以是100,如果是int型,结果是99,估计是精度造成的,但下 //次注意不要用pow,比较好的解决方式是直接乘,t*t,反正只用乘一次,但稳定性和正确 //率都会高很多 double t=sqrt(n); cout<<t<<endl; double k=pow(t,2); cout<<k<<endl; return 0; }
3.
特别注意一个思想上的问题
有些需要循环统计次数的问题,如果有一个全局变量计数,每次循环之前记得要清0
求公因子这次至少有两道题,直接遍历的方法很容易超时,这里介绍一种辗转相除法
例1 。求两个正数8251和6105的最大公因数。
(分析:辗转相除→余数为零→得到结果)
解:8251=6105×1+2146
显然8251与6105的最大公因数也必是2146的因数,同样6105与2146的公因数也必是8251的因数,所以8251与6105的最大公因数也是6105与2146的最大公因数。
6105=2146×2+1813
2146=1813×1+333
1813=333×5+148
333=148×2+37
148=37×4+0
则37为8251与6105的最大公因数。
以上我们求最大公因数的方法就是辗转相除法。也叫欧几里德算法,它是由欧几里德在公元前300年左右首先提出的。
int gcd1(int a,int b) { int temp; if(a==0||b==0) return -1; if(a<b) { temp=a;a=b;b=temp;} //求最小值最大值,大的用a表示,小的用b表示 while(b!=0) //用循环求最大公约数 { temp=a%b; a=b; b=temp; } if(a==1) return -1; return a; //返回最大公约数 }