一、试题A:门牌制作
二、试题B: 既约分数
三、试题C:蛇形填数
四、试题D:跑步锻炼
五、试题E:七段码
六、试题F:成绩统计
七、试题G:回文日期
八、试题H:子串分值和
九、试题I:平面切分
十、试题J:字串排序
一、试题A:门牌制作(5分)
【问题描述】
小蓝要为一条街的住户制作门牌号。
这条街一共有 2020 位住户,门牌号从 1 到 2020 编号。
小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符,最后根据需要将字
符粘贴到门牌上,例如门牌 1017 需要依次粘贴字符 1、0、1、7,即需要 1 个
字符 0,2 个字符 1,1 个字符 7。
请问要制作所有的 1 到 2020 号门牌,总共需要多少个字符 2?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
模拟:
代码如下:
//ans = 624
#include<iostream>
using namespace std;
#define ll long long
int ans;
int main(){
for(int i = 1; i <= 2020; i ++ ){
int n = i;
while(n != 0){
if(n % 10 == 2) ans ++;
n /= 10;
}
}
cout<<ans;
return 0;
}
二、试题B: 既约分数(5分)
如果一个分数的分子和分母的最大公约数是 1,这个分数称为既约分数。
例如,34 , 52 , 18 , 71 都是既约分数。
请问,有多少个既约分数,分子和分母都是 1 到 2020 之间的整数(包括 1 和 2020)?
【答案提交】
这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个
整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
代码如下:
//ans = 2481215
#include<iostream>
using namespace std;
#define ll long long
int g,ans;
int gcd(int a,int b){
if(b == 0)
return a;
else
return gcd(b,a%b);
}
int main(){
for(int c = 1; c <= 2020; c ++){
for(int d = 1; d <= 2020; d ++){
g = gcd(c,d);
if(g == 1) ans ++;
}
}
cout<<ans;
return 0;
}
三、试题C:蛇形填数(10分)
【问题描述】
如下图所示,小明用从 1 开始的正整数“蛇形”填充无限大的矩阵。
1 2 6 7 15 …
3 5 8 14 …
4 9 13 …
10 12 …
11 …
…
(1)
容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列
的数是多少?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
方法一:模拟:
// ans = 761
#include<iostream>
using namespace std;
#define ll long long
const int N = 100;
int a[N][N];
int main(){
int tot = 1,i = 1, j = 1;
a[i][j] = tot;
while(1){
if(j >= 60) break;
//往右走一步
j ++;a[i][j] = ++tot;
//往斜左走
while(j != 1){
i ++; j --;
a[i][j] = ++tot;
}
//往下走一步
i++;a[i][j] = ++tot;
//往斜右走
while(i != 1){
j ++; i --;
a[i][j] = ++tot;
}
}
for(int i = 1; i <= 20; i ++ ){
for(int j = 1; j <= 20; j ++ ){
cout<<a[i][j]<<" ";
}
puts("");
}
cout<<a[20][20];
return 0;
}
方法二:
数据范围不大,我们可以手写,但是在我手写的时候,发现对角线上它们之间的差成等差数列,于是发现给出的(20,20)也在对角线上
1 5 13 25 41 61
它们差的公差为d = 4
ans = 前一个数+公差d
代码如下:
#include<iostream>
using namespace std;
#define ll long long
int main(){
int n = 20;
int sn = 1 + (n - 1) * (4 + 4 * (n - 1))/2;
cout<<sn;
return 0;
}
四、试题D:跑步锻炼
【问题描述】
小蓝每天都锻炼身体。
正常情况下,小蓝每天跑 1 千米。如果某天是周一或者月初(1 日),为了
激励自己,小蓝要跑 2 千米。如果同时是周一或月初,小蓝也是跑 2 千米。
小蓝跑步已经坚持了很长时间,从 2000 年 1 月 1 日周六(含)到 2020 年
10 月 1 日周四(含)。请问这段时间小蓝总共跑步多少千米?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
日期问题:
- 模拟
那些算8871的,可能是没判断闰年,注意一下
代码如下:
//ans = 8879
#include<iostream>
using namespace std;
#define ll long long
int days[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
bool isleap(int n){
if(n % 400 == 0) return true;
if(n % 100 != 0 && n % 4 == 0) return true;
return false;
}
int main(){
int y = 2000,m = 1,d = 1,w = 6;
int cnt = 0;
while(1){
if(y == 2020 && m == 10 && d == 2) break;
if(w == 1 || d == 1) cnt++;
cnt++,d++,w++;
if(m == 2){
if(isleap(y)){
if(d > 29) m ++, d = 1;
}else{
if(d > 28) m ++, d = 1;
}
}
else if(d > days[m]){
m ++, d = 1;
}
if(m > 12){
y ++, m = 1;
}
if(w > 7) w = 1;
}
cout<<cnt;
return 0;
}
五、试题E:七段码(待补)
六、试题F:成绩统计
【样例输入】
7
80
92
56
74
88
100
0
【样例输出】
71%
43%
【评测用例规模与约定】
对于 50% 的评测用例,1 ≤ n ≤ 100。
对于所有评测用例,1 ≤ n ≤ 10000。
代码如下:
#include<iostream>
using namespace std;
#define ll long long
double ans1,ans2;
int n,grade;
int main(){
cin >> n;
for(int i = 0; i < n; i ++ ){
cin >> grade;
if(grade >= 60) ans1 ++;
if(grade >= 85) ans2 ++;
}
ans1 = ans1 / n * 100; ans2 = ans2 / n * 100;
printf("%d%%\n",(int)(ans1 + 0.5));
printf("%d%%\n",(int)(ans2 + 0.5));
return 0;
}
七、试题G:回文日期
【样例输入】
20200202
【样例输出】
20211202
21211212
【评测用例规模与约定】
对于所有评测用例,10000101 ≤ N ≤ 89991231,保证 N 是一个合法日期的
8 位数表示。
代码如下:
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
#define ll long long
int n;
bool flag1 = true,flag2 = true;
string res1,res2;
int days[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
bool isleay(int n) {
if(n % 400 == 0) return true;
if(n % 100 != 0 && n % 4 == 0) return true;
return false;
}
void work(int y,int m,int d) {
string s1 = "",s2 = "",s3 = "";
while(y != 0) {
s1 += y % 10 + '0';
y /= 10;
}
reverse(s1.begin(),s1.end());
if(m < 10) {
s2 += '0';
s2 += m % 10 + '0';
} else {
while(m != 0) {
s2 += m % 10 + '0';
m /= 10;
}
reverse(s2.begin(),s2.end());
}
if(d < 10) {
s3 += '0';
s3 += d % 10 + '0';
} else {
while(d != 0) {
s3 += d % 10 + '0';
d /= 10;
}
reverse(s3.begin(),s3.end());
}
string s = s1 + s2 + s3;
if(flag1) {
bool ans1 = true;
for(int i = 0, j = s.size() - 1; i < s.size()/2; i ++ , j --) {
if(s[i] != s[j]) ans1 = false;
}
if(ans1) flag1 = false,res1 = s;
}
bool ans2 = false;
if(s[0] == s[2] && s[2] == s[5] && s[5] == s[7]){
if(s[1] == s[3] && s[3] == s[4] && s[4] == s[6]){
ans2 = true;
}
}
if(ans2) flag2 = false,res2 = s;
}
int main() {
cin >> n;
int y = n / 10000;
int m = n % 1000 / 100;
int d = n % 100;
while(flag1 || flag2) {
d ++;
work(y,m,d);
if(m == 2) {
if(isleay(n)) {
if(d > 29) m ++,d = 1;
} else {
if(d > 28) m ++,d = 1;
}
} else if(d > days[m]) {
m ++, d = 1;
}
if(m > 12) y ++,m = 1;
}
cout<<res1<<endl;
cout<<res2<<endl;
return 0;
}