写在前面:今天上午的河大赛把我给写自闭了,倒不是因为题目有多难,而是我脑子抽了。古风排序写出来了,简单的没写出来。3进制和8进制之间的相互转换,按理应该是先把3进制或8进制转成10进制,再把得到的这个10进制转成8进制和3进制,可是我直接写的10进制转3进制和8进制。。。。我当时傻逼了。还有就是从一篇.txt后缀的英语文章中找出最长的单词(可能有多个),我第一思路是把目前遍历到的最长单词存入vector,同样长度也存进去,要是遇到了更长的就把vector清空全部重新存入更长的单词。这种算法不仅效率很低,而且我没有得到正确的输出。。。。应该先全部存入vector再sort排序的,有时间再把那俩题写成代码吧。现在刷PAT乙级和CCF历年真题,PAT9号考,CCF16号考,15号还有个英语四级 估计这回四级要凉。柿子先捏软的,先把历年真题的第一题做一下吧。总共15道题只有一道80分。哎 估计刷历届第二题就会被虐了。
201809-1. 卖菜
解题思路:
建立俩个数组,分别是第一天的菜价和第二天的菜价。第一天的菜价由输入得到。第二天的菜价就按照题意来:①编号为1的商店只有一个相邻的商店2;②编号为n的商店只有一个相邻的商店n-1;③其余的编号为i的商店有两个相邻的商店i-1和i+1。最后来个for-each循环输出第二天菜价即可。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; 8 int a[n]; //第一天的菜价 9 for (int i = 0; i < n; i++) 10 { 11 cin >> a[i]; 12 } 13 //去尾法取整 14 int b[n]; //第二天的菜价 15 b[0] = (a[0]+a[1])/2; //编号为1的商店只有一个相邻的商店2 16 for (int i = 1; i < n-1; i++) //中间编号为i的商店有两个相邻的商店i-1和i+1 17 { 18 b[i] = (a[i-1]+a[i]+a[i+1])/3; 19 } 20 b[n-1] = (a[n-1]+a[n-2])/2; //编号为n的商店只有一个相邻的商店n-1 21 for(auto i:b) //for-each循环遍历数组b并进行输出 22 { 23 cout << i << " "; 24 } 25 return 0; 26 }
201803-1. 跳一跳
解题思路:
total为每一局游戏的总分,score为每一次跳的得分。接着按照题目意思来就行了:1.如果没跳到方块上则游戏结束;2.如果跳到方块上但没有跳到中心点得一分;3.跳到方块的中心点的时候又分三种情况:①若是开局第一次跳,则得2分;②若上次得1分,则这次得2分;③连续跳到方块中心点,则本次跳跃得分在上一次得分基础上再加2分。把题目提供的这个思路转换成代码就行了,每次跳跃得分score累加到total,在游戏结束时total的值即为每一局游戏的总分。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 int total=0, score=0; //total为总分,score为每一次跳的得分 8 bool isVirgin = true; //用来判断是不是第一次 9 while(cin >> n) //开始一局游戏 10 { 11 if(n==0) //0表示此次跳跃没有跳到方块上(此时游戏结束) 12 { 13 break; 14 } 15 else //如果跳到了方块上 16 { 17 if(n == 1) //跳到了方块上,但没有跳到方块的中心则获得1分 18 { 19 score = 1; 20 total += score; 21 } 22 if(n == 2) //跳到了方块中心 23 { 24 if(isVirgin) //本局游戏第一次跳跃就跳到了方块中心,则此次得分为2分 25 { 26 score = 2; 27 isVirgin = false; //以后就不是第一次了 28 } 29 else if(score == 1) //若上一次的得分为1,则此次得分为2分 30 { 31 score = 2; 32 } 33 else //连续跳到方块中心时,此次得分在上一次得分的基础上加2分 34 { 35 score += 2; 36 } 37 total += score; 38 } 39 } 40 } 41 cout << total << endl; 42 return 0; 43 }
201712-1. 最小差值
解题思路:
从n个整数中找到相差最小的俩个数,直接对数组进行sort,然后for循环来比较排序后的俩个数之间的差值,调用min函数来把俩者间的较小值赋给ans,最后输出的ans就是这个数组的最小差值。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; 8 int a[n]; 9 for (int i = 0; i < n; i++) 10 { 11 cin >> a[i]; 12 } 13 sort(a,a+n); //对数组中的元素进行升序排序 14 int ans = 1e5; //ans用来存放最小值 15 for (int i = 0; i < n-1; i++) 16 { 17 ans = min(ans,a[i+1]-a[i]); //调用min函数来返回俩者中的最小值 18 } 19 cout << ans << endl; 20 return 0; 21 }
201709-1. 打酱油
解题思路:
这题就是贪心算法,能买多少算多少,能买5瓶就买5瓶,不能买5瓶的话,能买3瓶就买3瓶,反正尽可能地参与优惠活动。我用了三个while语句来实现这个算法。还是某大佬的贪心算法牛逼,见第8行注释,一行出结果。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; //小明可用于买酱油的钱数 8 //cout<<n/50*7+n%50/30*4+n%50%30/10; 大佬的贪心算法,直接AC 9 int count = 0; //小明可以买到的酱油数 10 while(n>=50) //看看小明的钱能不能买5瓶酱油 11 { 12 count += 7; //每买5瓶送2瓶 13 n -= 50; 14 } 15 while(n>=30) //看看小明的钱能不能买3瓶酱油 16 { 17 count += 4; //每买3瓶送1瓶 18 n -= 30; 19 } 20 while(n>0) 21 { 22 count += 1; //能买多少是多少 23 n -= 10; 24 } 25 cout << count << endl; 26 return 0; 27 }
201703-1. 分蛋糕
解题思路:
这题主要就是这三个步骤①尽可能地让朋友拿到蛋糕的重量大于k,不大于k就继续给他蛋糕,直到该朋友手上的蛋糕大于k为止;②大于k就给下一个朋友蛋糕,重复步骤①,直到蛋糕分完才进入步骤③;③只要朋友手上有蛋糕就算他分到了蛋糕,计数器count加一。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n,k; //n块蛋糕,小明想分给每个朋友至少重量为k的蛋糕 7 cin >> n >> k; 8 int count = 0; //count为拿到蛋糕的朋友数 9 int weight = 0; //每个朋友拿到蛋糕的重量 10 for (int i = 1; i <= n; i++) 11 { 12 int temp; 13 cin >> temp; 14 weight += temp; 15 if(weight >= k) 16 { 17 count++; 18 weight = 0; 19 } 20 } 21 if(weight > 0) 22 { 23 count++; 24 } 25 cout << count << endl; 26 return 0; 27 }
201612-1. 中间数
解题思路:
寻找中间数前先对整数序列进行排序,然后无脑for循环来暴力破解就行了。第一个for循环是用来找中间数的,第二个for循环是用来判断这个序列中比第一个for循环中假定的那个中间数大的和比它小的是否相等,若相等则输出中间数并把flag标记为true,flag用来判断是否找到了中间数,若无脑for循环结束之后都没有找到中间数则输出-1。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; //整数序列中数字的个数 7 cin >> n; 8 int a[n]; 9 for (int i = 0; i < n; i++) 10 { 11 cin >> a[i]; 12 } 13 sort(a,a+n); //对整数序列进行排序 14 bool flag = false; //是否找到了中间数 15 //无脑for循环暴力破解 16 for (int i = 0; i < n; i++) //这个for循环是用来找中间数的 17 { 18 int count_low = 0; //比中间数小的数 19 int count_up = 0; //比中间数大的数 20 for (int j = 0; j < n; j++) //这个for循环是用来看整数序列中有多少比它大有多少比它小 21 { 22 if(a[j]>a[i]) 23 { 24 count_up++; 25 } 26 if(a[j]<a[i]) 27 { 28 count_low++; 29 } 30 } 31 if(count_low == count_up) 32 { 33 flag = true; 34 cout << a[i] << endl; 35 break; 36 } 37 } 38 if(!flag) //若没有找到中间数则输出-1 39 { 40 cout << -1 << endl; 41 } 42 return 0; 43 }
201609-1. 最大波动
解题思路:
这道最大波动的题和前面的那道最小差值的题可以说是用同一个解题套路。只是这题无需对数组排序,直接比较相邻数字的绝对差值,调用max函数来把俩者间的较大值赋给ans,最后输出的ans就是这个数组的最大波动。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; //小明拿到的收盘价格的连续天数 7 cin >> n; 8 int a[n]; 9 for (int i = 0; i < n; i++) 10 { 11 cin >> a[i]; //每天的收盘价格 12 } 13 int ans = -1e5; //ans用来存放最大波动 14 for (int i = 0; i < n-1; i++) 15 { 16 ans = max(ans,abs(a[i+1]-a[i])); //调用min函数来返回俩者中的最大值 17 } 18 cout << ans << endl; 19 return 0; 20 }
201604-1. 折点计数
解题思路:
这题最关键的部分就在于找折点。如果数组中相邻俩天销售量的变化量跟前一天销售量的变化量符号是不一样的(一正一负),就说明这个点是折点,用count计录折点数,最后输出折点的数量就行了。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; //表示一个商店连续n天的销售量 7 cin >> n; 8 int a[n]; 9 int count = 0; //用来记录折点的数量 10 int change; //相邻俩天的变化量 11 bool flag = true; //前俩天一直为true 12 for (int i = 0; i < n; i++) 13 { 14 cin >> a[i]; //商店每天的销售量 15 if(i > 0) 16 { 17 if(!flag) 18 { 19 if((a[i]-a[i-1]<0&&change>0)||(a[i]-a[i-1]>0&&change<0)) 20 { 21 count++; 22 } 23 change = a[i] - a[i-1]; 24 } 25 else 26 { 27 change = a[i]-a[i-1]; 28 flag =false; 29 } 30 } 31 } 32 cout << count << endl; 33 return 0; 34 }
201512-1. 数位之和
解题思路:
我输入的是字符型数字,直接把每一位字符型数字转换成int型累加到sum输出即可。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 string n; 7 cin >> n; //字符串型数字 8 int sum = 0; 9 for (int i = 0; i < n.length(); i++) 10 { 11 sum += n[i]-'0'; //累加各位数字 12 } 13 cout << sum << endl; 14 return 0; 15 }
201509-1. 数列分段
解题思路:
这题跟前面那个折点的题有点类似啊。这题中,只要相邻的俩个数字数值不相等,就说明存在一个断点,用count来记录断点的数量,断点的数量加一就是数列的段数。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; 8 int a[n]; 9 int count = 0; //数有多少个断点 10 for (int i = 0; i < n; i++) 11 { 12 cin >> a[i]; 13 if(i > 0) 14 { 15 if(a[i] != a[i-1]) //相邻俩个数不相同就是一个断点 16 { 17 count++; 18 } 19 } 20 } 21 cout << count+1 << endl; //数列的段数就是在断点的基础上加一 22 return 0; 23 }
201503-1. 图像旋转
解题思路:
额,这题只有80分,就不写思路了,丢人。
80分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int row,col; //图像矩阵的行数和列数 7 cin >> row >> col; 8 int a[row][col]; 9 for (int i = 0; i < row; i++) 10 { 11 for (int j = 0; j < col; j++) 12 { 13 cin >> a[i][j]; 14 } 15 } 16 for (int i = col-1; i >= 0; i--) 17 { 18 for (int j = 0; j < row; j++) 19 { 20 if(j!=0) 21 { 22 cout << " "; 23 } 24 cout << a[j][i]; 25 } 26 cout << endl; 27 } 28 return 0; 29 }
100分代码: 80分和100分的区别就在于数组a是一个容量足够大的全局变量。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int a[1005][1005]; 5 int main() 6 { 7 int row,col; //图像矩阵的行数和列数 8 cin >> row >> col; 9 for (int i = 0; i < row; i++) 10 { 11 for (int j = 0; j < col; j++) 12 { 13 cin >> a[i][j]; 14 } 15 } 16 for (int i = col-1; i >= 0; i--) 17 { 18 for (int j = 0; j < row; j++) 19 { 20 if(j != 0) 21 { 22 cout << " "; 23 } 24 cout << a[j][i]; 25 } 26 cout << endl; 27 } 28 return 0; 29 }
201412-1. 门禁系统
解题思路:
看完题目之后第一反应就是建立一个map用来记录读者来访,其中key是读者的编号,value是读者的来访次数。边输入边输出即可。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 map<int,int> m; 7 //map用来记录读者来访,其中key是读者的编号,value是读者的来访次数 8 int n; 9 cin >> n; 10 for (int i = 0; i < n; i++) 11 { 12 int temp; 13 cin >> temp; 14 m[temp]++; 15 cout << m[temp] << " "; 16 } 17 return 0; 18 }
201409-1. 相邻数对
解题思路:
这题跟前面的最大波动最小差值很相似。不用对数组排序,直接for循环遍历,输出差值为1的相邻数字即可。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; 8 int a[n]; 9 for (int i = 0; i < n; i++) 10 { 11 cin >> a[i]; 12 } 13 sort(a,a+n); //对数组中的元素进行升序排序 14 int count = 0; //用来记录相邻数对 15 for (int i = 0; i < n-1; i++) 16 { 17 if(a[i+1]-a[i] == 1) 18 { 19 count++; 20 } 21 } 22 cout << count << endl; 23 return 0; 24 }
201403-1. 相反数
解题思路:
这第一题真的都很相似啊,无脑for循环来暴力破解吧,如果在数组中存在相反数则count++,需要注意的是,count记录的是相反数的个数,并不是相反数的对数,最后输出的时候需要输出的是count/2。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; 8 int a[n]; 9 for (int i = 0; i < n; i++) 10 { 11 cin >> a[i]; 12 } 13 int count = 0; //用来记录数组中有多少个数有相反数 14 //暴力破解吧 无脑for循环 15 for (int i = 0; i < n; i++) 16 { 17 for (int j = 0; j < n; j++) 18 { 19 if(a[i]==-a[j]) //判断是不是相反数 20 { 21 count++; 22 } 23 } 24 } 25 cout << count/2 << endl; //count除以2才是数组中相反数的对数 26 return 0; 27 }
201312-1. 出现次数最多的数
解题思路:
这题直接用map来进行操作,其中map的key是正整数,value是其在数组中出现的次数。ans用来存放出现次数最多的正整数,max用来记录出现最多的次数,for-each循环遍历map,若某个数出现次数大于max,更新出现最多的次数max和出现最多次的正整数ans。最后输出ans即可。
100分代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 map<int,int> m; //map的key是正整数,value是其在数组中出现的次数 7 int n; 8 cin >> n; //n个正整数 9 int a[n]; 10 for (int i = 0; i < n; i++) //输入正整数并记录它们在数组中出现的次数 11 { 12 int temp; 13 cin >> temp; 14 m[temp]++; 15 } 16 int ans,max=0; //ans用来存放出现次数最多的正整数,max用来记录出现最多的次数 17 for(auto it:m) //for-each循环遍历map 18 { 19 if(it.second > max) //若某个数出现次数大于max 20 { 21 max = it.second; //更新出现最多的次数max 22 ans = it.first; //更新出现最多次的正整数 23 } 24 } 25 cout << ans << endl; 26 return 0; 27 }