2021年新生赛第二场题解

南师大计电院2021年新生赛第二场题解,由njnu19210134和njnu19210310合作完成。代码为c++,不作为原题目的完美参考。

所有程序案例为C++,且使用了#include进行偷懒,不应当养成这样的习惯。

此题解仅供参考,不一定准确和完美。

#1 A1-2 分支结构练习:三数的特征值

输入任意三个整数,输出其中的中间值和最大值。

输出一行,两个整数,前者是中间值,后者是最大值。

和上次的第一题没啥区别,依然交换排序完之后只输出第二个和第三个就好。

这里给出不用swap()函数的做法。

1
2
3
4
5
6
7
8
9
10
11
12
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,b,c,t;
cin>>a>>b>>c;
if (a>=b) {t=a; a=b; b=t;}
if (b>=c) {t=b; b=c; c=t;}
if (a>=b) {t=a; a=b; b=t;}
cout<<b<<' '<<c;
return 0;
}

注意之后要重新判断a和b。

#2 A4-1 回文数专题:数字之和

输入任意正整数,输出该整数中所有数字之和。

利用while()循环,将输入的正整数作为while的参数

1
2
3
4
while(num){
ans+=num%10;
num/=10;
}

ans+=num%10得到num的个位数,num/=10去掉num的个位,原来的十位成为个位。直到num不断/10得到0,退出循环。

总代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<bits/stdc++.h>
using namespace std;
int main()
{
int num,ans=0;
cin>>num;
while(num){
ans+=num%10;
num/=10;
}
cout<<ans;
return 0;
}

#3 A4-2 回文数专题:反数

输入任意正整数,输出和该数次序相反的数。

修改上一题的代码,ans加完个位数之后自乘10,即可移至10位。注意最后要除以10把多出来的去掉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<bits/stdc++.h>
using namespace std;
int main()
{
int num,ans=0;
cin>>num;
while(num){
ans+=num%10;
ans*=10;
num/=10;
}
ans/=10;
cout<<ans;
return 0;
}

#4 A4-3 回文数专题:回文数判断

输入任意正整数,判断该数是否是回文数。若是,则输出Yes;否则输出No。

借用上一题,如果一个数的反数是自己,那就是回文数。

Int一个n来暂存输入的num。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<bits/stdc++.h>
using namespace std;
int main()
{
int num,ans=0;
cin>>num;
int n=num;
while(num){
ans+=num%10;
ans*=10;
num/=10;
}
ans/=10;
if(n==ans) cout<<"Yes";
else cout<<"No";
return 0;
}

#5 A4-4 回文数专题:回文数个数

输入正整数n,输出[1, n]中的回文数个数。

将上一题的答案打包成函数,cout改为return,再删掉cin,主函数里写一个for循环遍历1到n即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<bits/stdc++.h>
using namespace std;
bool ifh(int num){
int n=num;
int a=0;
while(num){
a+=num%10;
a*=10;
num/=10;
}
a/=10;
if(n==a) return 1;
else return 0;
}
int main()
{
int n;
cin>>n;
int ans=0;
for(int i=1;i<n;i++){
if(ifh(i)==1) ans++;
}
cout<<ans;
return 0;
}

#6 A5-1 超级素数判断

若一个素数,依次舍掉个位,得到的每个整数都是素数,则该素数称为超级素数。
输入任意正整数,判断该数是否是超级素数。若是,则输出Yes;否则输出No。

测试案例:
输入:

1
2333

输出:

1
Yes

(解释:2333,233,23,2均为素数)


解:首先还是要用到那个重要的函数,isprime

1
2
3
4
5
6
bool isprime(int a)
{
if(a==1) return 0;
for(int i=2;i*i<=a;i++) if(a%i==0) return 0;
return 1;
}

接下来要做的是每次舍去各位。根据c的计算规则,当整数进行除法时:

1
2
3
code:   b=a/10  
input: a=53 | a=2
output: b=5 | b=0

所以为舍去各位,只要让原数除10,接下来只要判断每次舍去后是不是素数。当然,什么时候结束呢,自然就是原数变成0时。

要注意的一点是,根据样例解释,原数也要进行判断,不能先舍去个位再进行判断。

示例代码如下。我的思路是“如果出现非素数则改变flag状态,如果检查完flag变化则出现过非素数”当然也可以“如果出现非素数直接跳出循环结算,检查完都不出现素数则输出Yes”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<bits/stdc++.h>
using namespace std;
int isprime(int a)
{
if(a==1) return 1;
for(int i=2;i*i<=a;i++) if((a%i)==0) return 1;
return 0;
}
int main()
{
int n,flag=0;
cin>>n;
if(n<10)
{
if(isprime(n)) cout<<"No"<<endl;
else cout<<"Yes"<<endl;
return 0;
}
else
{
while(n!=0)
{
flag+=isprime(n);
n=n/10;
}
}
if(flag==0) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}

#7 A5-2 超级素数的个数

输入正整数n,输出[2, n]中的超级素数的个数。

测试案例:
输入:

1
30

输出:

1
6

(解释:2,3,5,7,23,29是超级素数)


解:将上一题的代码作为子函数,逐一检查2-n的所有数是否为超级素数。

示例代码如下。当时为了保险起见加了b<10的判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<bits/stdc++.h>
using namespace std;
bool isprime(int a)
{
if(a==1) return 0;
for(int i=2;i*i<=a;i++) if((a%i)==0) return 0;
return 1;
}
bool issuperprime(int b)
{
if(b<10)
{
if(isprime(b)) return 1;
return 0;
}
else
{
while(b!=0)
{
if(!isprime(b)) return 0;
b=b/10;
}
}
return 1;
}
int main()
{
int n,ans=0;
cin>>n;
for(int i=2;i<=n;i++) ans+=issuperprime(i);
cout<<ans<<endl;
return 0;
}

#8 5-6 过去了多少天

输入两行。第一行是3个整数(年月日),用空格分开。第二行也是3个整数(年月日),用空格分开。
输出一行,1个整数,表示两个日期之间的天数。
题目保证日期数据的合理性,并且第一个日期不晚于第二个日期。

测试案例1:
输入:

1
2
2000 1 1
2000 1 1

输出:

1
0

测试案例2:
输入:

1
2
2000 1 1
2001 1 1

输出:

1
366

解:这道题就很,没有意义。要么直接通过两个日期算出差几天,要么一天天累加,看什么时候两个日期相同。我使用的是后者。

日期加减必然要考虑闰年的问题。写个判断函数就好。

1
2
3
4
bool isrun(int ye)
{
return ye%4==0&&ye%100!=0||ye%400==0;
}

我的示例程序如下。写的很丑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<bits/stdc++.h>
using namespace std;
int y,m,d,yy,mm,dd,t;
bool sameday()
{
if(y!=yy) return 1;
else if(m!=mm) return 1;
else if(d!=dd) return 1;
return 0;
}
bool isrun(int ye)
{
return ye%4==0&&ye%100!=0||ye%400==0;
}
int main()
{
int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int b[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
cin>>y>>m>>d;
cin>>yy>>mm>>dd;
while(sameday())
{
t++;
d++;
if(isrun(y))
{
if(d==b[m])
{
m++;
t++;
d=1;
}
}
else
{
if(d==a[m])
{
t++;
m++;
d=1;
}
}
if(m==13)
{
y++;
m=1;
}
}
cout<<t<<endl;
return 0;
}

#9 1-2 斐波那契数列的和

输入两个正整数k1,k2(保证k1<=k2)。输出斐波那契数列的第k1项到第k2项的和。

测试案例:
输入:

1
3 6 

输出:

1
18

(解释2+3+5+8=18)


解:两个思路。一种是“先算到k1项,然后从这里开始累加到k2项”,一种是“先算到k2项,然后返回k1项开始累加”。理论上前者可以不用存储,而后者需要存储。

斐波那契数列的算法不再赘述。示例代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
#include<bits/stdc++.h>
using namespace std;
int main()
{
int s,f,t[100010],ans=0;
cin>>s>>f;
t[1]=1;t[2]=1;
for(int i=3;i<=f;i++) t[i]=t[i-1]+t[i-2];
for(int i=s;i<=f;i++) ans+=t[i];
cout<<ans<<endl;
return 0;
}

#10 2-1 单个数的3N+1猜想

请你任意输入一个整数x(1<x<100),按照以下法则进行变换,最终数字一定会变成为1。如果x是一个奇数,则下一步变为3x+1;如果x是一个偶数,则下一步变成x/2。
输入正整数x,输出x经过该变换到达1的步骤数。
测试案例:
输入:

1
6

输出:

1
8

(解释: 6->3->10->5->16->8->4->2->1)


解:照着它写的模拟就可以了。判断奇偶数只要看a%2是几。如果是1,那就是奇数。

示例代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,t=0;
cin>>a;
while(a!=1)
{
if(a%2==0) a=(a/2);
else a=(a*3+1);
t++;
}
cout<<t<<endl;
return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!