第一题:跑步训练(5分)
小明要做一个跑步训练。
初始时,小明充满体力,体力值计为 10000 。如果小明跑步,每分钟损耗 600 的体力。如果小明休息,每分钟增加 300 的体力。体力的损耗和增加都是均匀变化的。
小明打算跑一分钟、休息一分钟、再跑一分钟、再休息一分钟……如此循环。如果某个时刻小明的体力到达 0 ,他就停止锻炼。
请问小明在多久后停止锻炼。为了使答案为整数,请以秒为单位输出答案。答案中只填写数,不填写单位。
考点 模拟
#include<bits/stdc++.h>
using namespace std;
int main(){
int k = 10000;
int i = 0; //每当i = 60 t 变换一次
int t = 0; //t = 0 体力减少,t = 1 体力增加
int s; //记录秒数
while(1) //直接用秒计算
{ i++;
s++;
if(!t)
{ k = k - 10;
if(k == 0)
{ cout << s << endl; //3880
break;
}
if(i % 60 == 0)
t = 1;
}
else
{ k = k + 5;
if( i % 60 == 0)
t = 0;
}
}
return 0;
}
第二题:纪念日(5分)
2020 年 7 月 1 日是中国 共 产 党 成立 99 周年纪念日。
中国 共 产 党 成立于 1921 年 7 月 23 日。
请问从 1921 年 7 月 23 日中午 12 时到 2020 年 7 月 1 日中午 12 时一共包含多少分钟?
#include<bits/stdc++.h>
using namespace std;
int check(int y)
{ if( y % 400 == 0 || y % 100 != 0 && y % 4 == 0)
return 366;
else
return 365;
}
int main(){
int sum = 0;
for(int i = 1922; i <= 2019; i ++)
{ sum += check(i);
}
cout << sum << endl;
int sum2 = 0;
if(check(2020) == 366) cout << "y"; //闰年 枚举 8 ,9,10,11,12 的月份 1,2,3,4,5,6 ,
if(check(1991) == 365) cout << "y"; //非闰年 8,9,10,11,12 的月份
//之后从7月23到31的日子,最后sum 加上1922 年和 2020 年的日期 * 24 * 60
//完全手动计算,大佬都是用Excel,我是菜狗只会代码+手动算
//52038720
return 0;
}
第三题:合并检测(10分)
题目描述
新冠疫情由新冠病毒引起,最近在 A 国蔓延,为了尽快控制疫情, A 国准备给大量民众进病毒核酸检测。
然而,用于检测的试剂盒紧缺。
为了解决这一困难,科学家想了一个办法:合并检测。即将从多个人( k 个)采集的标本放到同一个试剂盒中进行检测。如果结果为阴性,则说明这 k 个人都是阴性,用一个试剂盒完成了 k 个人的检测。如果结果为阳性,则说明至少有一个人为阳性,需要将这 k 个人的样本全部重新独立检测(从理论上看,如果检测前 k−1 个人都是阴性可以推断出第 k 个人是阳性,但是在实际操作中不会利用此推断,而是将 k 个人独立检测),加上最开始的合并检测,一共使用了 k+1 个试剂盒完成了 k 个人的检测。
A 国估计被测的民众的感染率大概是 1,呈均匀分布。请问 k 取多少能最节省试剂盒?
#include<bits/stdc++.h>
using namespace std;
int main(){
/* 思路是暴力枚举一下,假设100个人有一个人得病,
看一下当前i个人一起测最多用多少个试剂盒
如果100/i不够除,让剩下的人都是单独用一个试剂盒测
如果能够整除,需要再加上i个试剂盒,因为必然会有一个试剂盒检测出病人,需要每个人单独测
//数学问题
*/
int min = 1000;
int k;
int sum;
for(int i = 2; i <= 100; i ++)
{
sum = 100 / i + i;
if(100 % i != 0)
{ sum += 100 % k;
}
if(sum < min)
{ min = sum;
k = i;
}
}
cout << k << endl; //10
return 0;
}
附件 prog.txt 中是一个用某种语言写的程序。
其中 REPEAT k 表示一个次数为 k 的循环。循环控制的范围由缩进表达,从次行开始连续的缩进比该行多的(前面的空白更长的)为循环包含的内容。
例如如下片段:
REPEAT 2: A = A + 4 REPEAT 5: REPEAT 6: A = A + 5 A = A + 7 A = A + 8 A = A + 9
该片段中从 A = A + 4 所在的行到 A = A + 8 所在的行都在第一行的循环两次中。
REPEAT 6: 所在的行到 A = A + 7 所在的行都在 REPEAT 5: 循环中。
A = A + 5 实际总共的循环次数是 2 × 5 × 6 = 60 次。
请问该程序执行完毕之后,A 的值是多少?
#include<bits/stdc++.h>
using namespace std;
int A;
int main(){
//这道题看了半天没明白啥意思,后来看了一下就是for循环换了一个说法,理解能力太差,没办法,多做题吧
for(int i = 1; i <= 2; i ++)
{ A = A + 4;
for(int j = 1; j <= 5; j ++)
{ for(int k = 1; k <= 6; k ++)
{ A = A + 5;
}
A = A + 7;
}
A = A + 8;
}
A = A + 9;
cout << A << endl; //答案 403
return 0;
}
第五题:矩阵
题目描述
把 1∼2020 放在 2×1010 的矩阵里。要求同一行中右边的比左边大,同一列中下边的比上边的大。一共有多少种方案?
答案很大,你只需要给出方案数除以 2020 的余数即可。
这道题考的是dp,暂且还没学到这个算法,后面再补吧
第六题:整除序列(15分)
题目描述
有一个序列,序列的第一个数是 n,后面的每个数是前一个数整除 2,请输出这个序列中值为正数的项。
【输入格式】
输入一行包含一个整数 n。
【输出格式】
输出一行,包含多个整数,相邻的整数之间用一个空格分隔,表示答案。
【评测用例规模与约定】
对于 80% 的评测用例,1≤n≤109。
对于所有评测用例,1≤n≤1018。
#include<iostream>
using namespace std;
int main()
{
long long n;//long long 的范围大概 10的19次方 送分题了别忘记数据开大一些
cin>>n;
while(n>0)
{
printf("%lld ",n);
n=n/2;
}
return 0;
}
第七题:解码
小明有一串很长的英文字母,可能包含大写和小写。 在这串字母中,有很多连续的是重复的。小明想了一个办法将这串字母表达得更短:将连续的几个相同字母写成字母 + 出现次数的形式。
例如,连续的 5 个 a ,即 aaaaa ,小明可以简写成 a5 (也可能简写成 a4a 、 aa3a 等)。
对于这个例子:HHHellllloo ,小明可以简写成 H3el5o2 。为了方便表达,小明不会将连续的超过 9 个相同的字符写成简写的形式。
现在给出简写后的字符串,请帮助小明还原成原来的串
我写这道题时写了半个多小时,写的很复杂。题目读错了。最后还是AC了,哎,读题很重要
#include<iostream> //我写的很复杂的代码
#include<cstdio>
#include<cstring>
using namespace std;
int main(){
string s;
string st;
int flag = 0;
cin >> s;
int k1 = s.size()-1;
for(int i = 0; i < s.size(); i ++)
{ if(flag == 1) break;
if(s[i] >= 'A' && s[i] <= 'Z' || s[i] >= 'a' && s[i] <= 'z')
{
st += s[i];
}
else
{ int t = 0;
int k = 0;
string s2;
for(int j = i; j < s.size(); j ++)
{ if(s[j] >= '0' && s[j] <= '9')
{ t++;
s2 += s[j];
}
else
{ k = j;
break;
}
}
if(t == s.size() - i) flag = 1;
if(t > 2)
{ st += s2;
s2.clear();
}
else
{ int t2 = s2[0]-'0';
for(int i = 1; i <= t2 -1; i ++)
st += st[st.size()-1];
}
}
}
for(int i = 0; i < st.size(); i ++) cout <<st[i];
return 0;
}
就不写简单的代码思路
如果这个数是字母记录一下,下一个是数字字符的话,循环输出这个的这个字符
第八题:走方格
题目描述
在平面上有一些二维的点阵。
这些点的编号就像二维数组的编号一样,从上到下依次为第 1 至第 n 行,从左到右依次为第 1 至第 m 列,每一个点可以用行号和列号来表示。
现在有个人站在第 1 行第 1 列,要走到第 n 行第 m 列。只能向右或者向下走。
注意,如果行号和列数都是偶数,不能走入这一格中。
问有多少种方案。
【输入格式】
输入一行包含两个整数 n, m。
【输出格式】
3 4
2
输出一个整数,表示答案。
【评测用例规模与约定】
对于所有评测用例,1≤n≤30,1≤m≤30。
#include<iostream>
using namespace std;
const int N = 33;
int s[N][N];
int n,m,ans;
bool st[N][N];
int fx[2] = {0,1},fy[2] = {1,0};
void dfs(int x,int y)
{ if(x == n && y == m)
{
ans ++;
return;
}
for(int i = 0; i < 2; i ++)
{ int dx = x + fx[i];
int dy = y + fy[i];
if(!st[dx][dy] && x <= n && y <= m && !s[dx][dy])
{ st[dx][dy] = true; //标记走过了
dfs(dx,dy);
st[dx][dy] = false; //回溯
}
}
}
int main()
{ //我个人用的dfs搜索,看到网上有人用dp,属实是真牛啊,代码写的还很短,
// 还有贪心和dp没学还得加油 这个题的提交我是在c语言网提交的,如果有做的不对的地方,
// 还请帮忙说一声。
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
{ if(i % 2 == 0 && j % 2 == 0)
s[i][j] = 1; //标记这个点
}
st[1][1] = true;
dfs(1,1);
//ans 表示 有多少个走法 提升一下,这道题的思路我看着和落谷题单递归中的马走棋盘
cout << ans << endl;
return 0;
}
后面两道题一个是模拟+STL ,另一个是并查集,都不会,后面慢慢补