<span>程序设计与算法(一)第4周测验(2020春季)</span>
001:角谷猜想
- 总时间限制: 1000ms 内存限制: 65536kB
描述
- 所谓角谷猜想,是指对于任意一个正整数,如果是奇数,则乘3加1,如果是偶数,则除以2,得到的结果再按照上述规则重复处理,最终总能够得到1。如,假定初始整数为5,计算过程分别为16、8、4、2、1。
程序要求输入一个整数,将经过处理得到1的过程输出来。
输入
- 一个正整数N(N <= 2,000,000)
输出
- 从输入整数到1的步骤,每一步为一行,每一部中描述计算过程。最后一行输出"End"。如果输入为1,直接输出"End"。
样例输入
- 5
样例输出
5*3+1=16
16/2=8
8/2=4
4/2=2
2/2=1
End
思考
AC
#include <iostream>
using namespace std;
int main(){
long long N; //注意范围
scanf("%d",&N);
while (N != 1){
if (N%2 == 0){ //偶数
cout << N << "/2=" << N/2 << endl; //这题有毒,不能用printf()通过
N /= 2;
}else{
cout << N << "*3+1=" << N*3+1 << endl;
N = N*3+1;
}
}
printf("End\n");
return 0;
}
002:正常血压
- 总时间限制: 1000ms 内存限制: 65536kB
描述
- 监护室每小时测量一次病人的血压,若收缩压在90 - 140之间并且舒张压在60 - 90之间(包含端点值)则称之为正常,现给出某病人若干次测量的血压值,计算病人保持正常血压的最长小时数。
输入
- 第一行为一个正整数n,n < 100
- 其后有n行,每行2个正整数,分别为一次测量的收缩压和舒张压,中间以一个空格分隔。
输出
- 输出仅一行,血压连续正常的最长小时数。
样例输入
4
100 80
90 50
120 60
140 90
样例输出
- 2
思考
- no
AC
#include <iostream>
int main(){
int i,n,sum=0,p,q,max=0;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d %d",&p,&q);
if((p>=90&&p<=140)&&(q>=60&&q<=90)){
sum++; //正常则计数
if(sum>max){
max=sum; //记录小时数
}
}else sum=0;
}
printf("%d\n",max);
return 0;
}
003:数字反转
- 总时间限制: 1000ms 内存限制: 65536kB
描述
- 给定一个整数,请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零(参见样例2)。
输入
- 输入共 1 行,一个整数N。
- -1,000,000,000 ≤ N≤ 1,000,000,000。
输出
输出共 1 行,一个整数,表示反转后的新数。
样例输入
样例 #1:
- 123
样例 #2:
- -380
样例输出
样例 #1:
- 321
样例 #2:
- -83
AC
#include <iostream>
using namespace std;
int main(){
long long n,m=0;
scanf("%lld",&n);
if(n<0){
printf("-"); //输出负号
n=-n; //取正
}
while(n!=0){
m=m*10+n%10; ////原数个位相当于新数最高位
n /= 10; //整除10,相当于删除个位
}
printf("%lld\n",m);
return 0;
}
004:求特殊自然数
- 总时间限制: 1000ms 内存限制: 65536kB
描述
- 一个十进制自然数,它的七进制与九进制表示都是三位数,且七进制与九进制的三位数码表示顺序正好相反。编程求此自然数,并输出显示。
输入
- 无。
输出
- 三行:
- 第一行是此自然数的十进制表示;
- 第二行是此自然数的七进制表示;
- 第三行是此自然数的九进制表示。
样例输入
(无)
样例输出
(不提供)
思考
- 看到这道题,第一想法是数组,但又觉得太麻烦了,就打算试试直接弄,结果🆗
- 直接化七进制或九进制,先思考一下可能的七进制或九进制的三位数的范围,最小的数是七进制的(101)7,最大是九进制的(666)9,
- 再根据题意“七进制与九进制的三位数码表示顺序正好相反”进行枚举即可。
AC
#include <iostream>
using namespace std;
int main(){
int i,x,y,z;
for(i=100;i<667;i++){
x=i/100; //百位
y=i/10%10; //十位
z=i%100; //个位
if(x*7*7+y*7+z==z*9*9+y*9+x){
printf("%d\n",x*7*7+y*7+z);
printf("%d%d%d\n",x,y,z);
printf("%d%d%d\n",z,y,x);
}
}
return 0;
}
005:雇佣兵
- 总时间限制: 1000ms 内存限制: 65536kB
描述
- 雇佣兵的体力最大值为M,初始体力值为0、战斗力为N、拥有X个能量元素。
- 当雇佣兵的体力值恰好为M时,才可以参加一个为期M天的战斗期,战斗期结束体力值将为0。在同一个战斗期内,雇佣兵每连续战斗n天,战斗力就会上升1点,n为当前战斗期开始时的战斗力。
- 一个战斗期结束后,雇佣兵需要用若干个能量元素使其体力恢复到最大值M,从而参加下一个战斗期。每个能量元素恢复的体力值不超过当前的战斗力。每个能量元素只能使用一次。
- 请问:雇佣兵的战斗力最大可以到达多少。
输入
- 一行包括三个整数M、N、X,相邻两个整数之间用单个空格隔开。M、N、X均为不超过10000的正整数。
输出
- 输出一个整数,为雇佣兵的最大战斗力。
样例输入
- 5 2 10
样例输出
- 6
思考
- 体力的初始值是0,但是有能量元素,x>0,需要用能量元素恢复体力才能进行战斗。因此可以用一个while循环
- 当体力达到最大值M时,就进行为期M天的战斗。如果m>n,则n+=m/n,这时能量元素x-=m/n;如果m<n,直接输出n。
- 战斗结束后,体力值为0,用能量元素进行恢复。如果当前的能量元素小于所需的能量元素,即x<m/n,则直接输出n。
- 一直循环,直到能量元素用完。
AC
#include <iostream>
using namespace std;
int main(){
int M,X,N,num=0;
scanf("%d %d %d",&M,&N,&X);//体力,战斗力、能量元素
while(X>0){
if(M%N==0) //消耗能源元素
num=M/N;
else
num=M/N+1;
if(X<num) break;
X -= num;
N += M/N; //战斗
}
printf("%d\n",N);
return 0;
}
006:数字统计
- 总时间限制: 1000ms 内存限制: 65536kB
描述
- 请统计某个给定范围[L, R]的所有整数中,数字2出现的次数。
- 比如给定范围[2, 22],数字2在数2中出现了1次,在数12中出现1次,在数20中出现1次,在数21中出现1次,在数22中出现2次,所以数字2在该范围内一共出现了6次。
输入
- 输入共 1 行,为两个正整数 L 和 R,之间用一个空格隔开。
输出
- 输出共 1 行,表示数字 2 出现的次数。
样例输入
样例 #1:
2 22
样例 #2:
2 100
样例输出
样例 #1:
6
样例 #2:
20
思考
- 枚举+取余+判断
AC
#include <iostream>
using namespace std;
int main(){
int L,R,i,num=0,j;
scanf("%d %d",&L,&R);
for(i=L;i<=R;i++) //枚举范围
for(j=i;j>0;j=j/10)
if(j%10==2) num++; //判断是否为2
printf("%d\n",num);
return 0;
}
第四周全部题解,🆗。