说明:
有几个题是不会讲的,我只能保证大家拿保底分。
题目列表:
问题 A: 统计字母个数
思路:
把'a'到'z'放map里处理后输出即可。
参考题解:
#include <iostream>
#include <string>
#include <map>
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
std::string s;
std::map<char,int> mp;
for(int i = 0;i<26;i++) mp['a'+i] = 0;
while(cin >> s) {
for(auto &c:s) if(c>='a'&&c<='z') mp[c]++;
if(s[s.size()-1]=='#') break;
}
for(auto &i:mp) {
cout << i.first << ' ' << i.second << '\n';
}
return 0;
}
问题 B: 小数化分数1
思路:
以字符串形式读入小数,从第三个字符开始统计,分子初始化为0,分母初始化为1,分子每次乘以10再加上字符-'0'的值(或者直接异或48也能实现同样的效果),分母每次乘以10,把两个数都除以它们的最大公约数再输出即可。
参考题解:
#include <iostream>
#include <string>
#include <algorithm>
using std::cin;
using std::cout;
void solve() {
std::string n;cin >> n;
int fenzi = 0,fenmu = 1;
for(int i = 2;i<n.size();i++) {
fenzi = fenzi*10+(n[i]^48);
fenmu *= 10;
}
int gcd = std::__gcd(fenzi,fenmu);
cout << fenzi/gcd << '/' << fenmu/gcd << '\n';
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int T = 1;cin >> T;
while(T--) {
solve();
}
return 0;
}
问题 C: 筛排处理
思路:
把数据都放进set里面,注意一下输出的格式即可。
参考题解:
#include <iostream>
#include <set>
using std::cin;
using std::cout;
void solve(int &n) {
std::set<int> set;
for(int i = 1;i<=n;i++) {
int tmp;cin >> tmp;
set.insert(tmp);
}
int count = 0;
cout << set.size() << '\n';
for(auto &i:set) {
count++;
cout << i << " \n"[count%10==0];
}
if(count%10!=0) cout << '\n';
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n = 1;
while(cin >> n) {
if(n==0) {
cout << "0\n";
break;
}
solve(n);
cout << '\n';
}
return 0;
}
问题 D: 产生冠军
思路:
读入所有比赛结果,第一遍遍历时把每场比赛的胜者都放入winner候选人名单中(实际上就是丢进set中),第二遍遍历时把每场的败者从winner候选人名单中剔除,最后判断winner候选人名单的大小,如果size为1,则可以唯一确定winner,否则则不行。
参考题解:
#include <iostream>
#include <string>
#include <vector>
#include <set>
using std::cin;
using std::cout;
void solve(const int &n) {
std::vector<std::pair<std::string,std::string>> competitions;
std::set<std::string> set;
for(int i = 0;i<n;i++) {
std::string winner,loser;
cin >> winner >> loser;
competitions.emplace_back(winner,loser);
set.insert(winner);
}
for(int i = 0;i<n;i++) {
set.erase(competitions[i].second);
}
cout << (set.size()==1?"Yes\n":"No\n");
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n = 1;
while(cin >> n,n) {
solve(n);
}
return 0;
}
问题 F: 恺撒密码
思路:
基本的字符变换题,这里注意读入的问题即可。用C语言的gets()读入需要提前把上一行的换行符读掉,用C++的getline()读入时也要用cin.get()或者再用一个getline()把换行符读掉。
参考题解:
#include <iostream>
#include <string>
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n = 1;cin >> n;
// std::cin.get();
std::string s,temps;
getline(cin,temps);
getline(cin,s);
for(auto &c:s) {
if(c>='a'&&c<='z') {
cout << char('a'+(c-'a'+n)%26);
}else cout << char(c);
}
cout << std::endl;
return 0;
}
问题 G: 切割正方体
思路:
考察思维,所有能切出的立方体都不大于长方体的长宽高的最大公约数,因此我们只需要计算长宽高的最大公约数的因子个数即可。
参考题解:
#include <iostream>
#include <algorithm>
#include <vector>
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int length,width,height;
while(cin >> length >> width >> height,length||width||height) {
int common_gcd = std::__gcd(std::__gcd(length,width),height);
std::vector<int> factor;
for(int i = 1;i<=common_gcd/i;i++) {
if(common_gcd%i==0) {
factor.emplace_back(i);
if(i!=common_gcd/i) {
factor.emplace_back(common_gcd/i);
}
}
}
cout << factor.size() << '\n';
}
return 0;
}
问题 H: 核反应堆
思路:
模拟一下每一秒发生的事情即可。注意此处可能会爆int,因此要开long long。
参考题解:
#include <iostream>
using ll = long long;
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n = 1;
while(cin >> n,n!=-1) {
ll high=1,low=0;
for(int i = 1;i<=n;i++) {
ll temp_high = high,temp_low = low;
high = temp_high*3+temp_low*2;
low = temp_high+temp_low;
}
cout << high << ", " << low << '\n';
}
return 0;
}
问题 I: 天花板
思路:
实现向上取整即可。直接用写好的函数(<cmath>头文件中的ceil()函数)即可。
参考题解:
#include <iostream>
#include <cmath>
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n = 1;cin >> n;
for(int i = 1;i<=n;i++) {
double number;cin >> number;
cout << std::ceil(number) << '\n';
}
return 0;
}
问题 K: 统计立方数
思路:
打个表把unsigned int范围内的所有立方数都放进vector中,之后读入数据时去这个vector使用二分查找,如果找到了,则ans++,否则continue
参考题解:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using ll = long long;
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
std::vector<ll> cubes;
for(ll i = 1;i*i*i<=UINT_MAX;i++) {
cubes.emplace_back(i*i*i);
}
ll n,ans = 0;
while(cin >> n,n) {
if(std::binary_search(cubes.begin(),cubes.end(),n)) {
ans++;
}
}
cout << ans << std::endl;
return 0;
}
问题 M: 剪花布条
思路:
字串查找题,可以用暴力匹配、kmp算法等思路。我这里直接用<string>头文件的find()类函数实现的查找。
参考题解:
#include <iostream>
#include <string>
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
std::string s,subs;
while(cin >> s,s!="#") {
cin >> subs;
int index = 0,ans = 0;
while(s.find(subs,index)!=std::string::npos) {
index = s.find(subs,index)+subs.size();
ans++;
}
cout << ans << '\n';
}
return 0;
}
问题 N: 不要62
思路:
根据数据范围10^6,我直接使用最暴力的方法,遍历n到m,每个遍历到的数,都把它转成字符串,再使用<string>的find()函数来查找'4'和'62',如果找到了,count++,否则continue,最后输出m-n+1-count即可。
参考题解:
#include <iostream>
#include <string>
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n,m;
while(cin >> n >> m,n||m) {
int count = 0;
for(int i = n;i<=m;i++) {
std::string s = std::to_string(i);
if(s.find('4')!=std::string::npos||s.find("62")!=std::string::npos) {
count++;
}
}
cout << m-n+1-count << '\n';
}
return 0;
}
问题 O: 过原点的直线数
思路:
要判断是否存在点与原点(0,0)的连线也经过了其他点,最简单的方式是求出所有点(xi,yi)的最大公约数,都放进set中去重输出set的大小即可。
参考题解:
#include <iostream>
#include <set>
#include <algorithm>
using std::cin;
using std::cout;
void solve() {
int n;cin >> n;
std::set<std::pair<int,int>> slopes;
for(int i = 1;i<=n;i++) {
int x,y;cin >> x >> y;
int gcd = std::__gcd(x,y);
slopes.insert(std::make_pair(x/gcd,y/gcd));
}
cout << slopes.size() << '\n';
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int T = 1;
cin >> T;
while(T--) {
solve();
}
return 0;
}
问题 P: 数的计数
思路:
很明显的dfs题,注意写的时候容易爆int,记得开long long。
参考题解:
#include <iostream>
#include <cstring>
using ll = long long;
using std::cin;
using std::cout;
void dfs(int u,ll *a) {
if(a[u]!=-1) return;
a[u] = 1;
for(int i = 1;i<=u/2;i++) {
dfs(i,a);
a[u]+=a[i];
}
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
constexpr int N = 1e3+5;
ll a[N];
memset(a,-1,sizeof a);
int n;cin >> n;
dfs(n,a);
cout << a[n] << std::endl;
return 0;
}
问题 Q: 排列
思路:
dfs入门最经典的题目,不过此题要注意输出的格式。我就不写dfs了,直接用STL的全排列函数了。
参考题解:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
constexpr int N = 1e1+5;
int n = 1;cin >> n;
for(int i = 1;i<=n;i++) {
int a[N];
for(int j = 1;j<=4;j++) {
cin >> a[j];
}
std::sort(a+1,a+1+4);
std::vector<std::string> ans;
do {
std::string s;
for(int i = 1;i<=4;i++) s = s+char(a[i]^48);
ans.emplace_back(s);
}while(std::next_permutation(a+1,a+1+4));
for(int j = 0;j<ans.size();j++) {
cout << ans[j] << " \n"[(j+1)%6==0];
}
if(i!=n) cout << '\n';
}
return 0;
}
问题 R: 排列2
思路:
是上个题的hard版本,只需要注意全排列第一个元素为0时丢弃,其他情况都放进vector中,再排序去重,但是注意输出的格式。
参考题解:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int a,b,c,d;
int num[5];
while(cin >> a >> b >> c >> d,a||b||c||d) {
num[1] = a,num[2] = b,num[3] = c,num[4] = d;
std::sort(num+1,num+1+4);
std::vector<std::string> ans;
do {
if(num[1]==0) continue;
std::string s;
for(int i = 1;i<=4;i++) {
s = s + char(num[i]^48);
}
ans.emplace_back(s);
}while(std::next_permutation(num+1,num+1+4));
std::sort(ans.begin(),ans.end());
char last = ans[0][0];
for(int i = 0;i<ans.size();i++) {
if(ans[i][0]!=last) {
cout << '\n' << ans[i] << ' ';
last = ans[i][0];
}else {
cout << ans[i] << ' ';
}
}
cout << '\n' << '\n';
}
return 0;
}
问题 S: 最多拦截导弹数
思路:
第一眼看到题,还以为是最经典的动态规划的最长上升子序列模型题,结果只是一个很傻的贪心题,直接写即可。
参考题解:
#include <iostream>
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
constexpr int N = 1e3+5;
int n;
while(cin >> n,n) {
int height[N];
for(int i = 1;i<=n;i++) cin >> height[i];
int now = 30000,ans = 0;
for(int i = 1;i<=n;i++) {
if(now>=height[i]) {
now = height[i];
ans++;
}else break;
}
cout << ans << '\n';
}
return 0;
}
问题 T: 昊城的分割游戏
思路:
题目看着很唬人,以为要用什么很复杂的数据结构或者算法思想,但是推几个样例就会发现答案不是0就是1,而且只跟读入数据对4取模的值有关。
参考题解:
#include <iostream>
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n;cin >> n;
cout << (n%4==1||n%4==2?1:0) << std::endl;
return 0;
}