2018级计科1、计科2、网工、信安班第14周竞赛题题解

前言#

本文中的题目做法仅供参考,不一定是最简单或是最正确的方法。
每题附的程序源码均在当时通过了OJ测试,但随着时间的推移也有可能失效。
作者水平有限,如有疏漏,在所难免,望留言指出。

A#

Problem A: Balloon Comes!
分情况处理,除法时注意判断一下能否整除即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
char c;
int a,b;
cin>>c>>a>>b;
if(c=='+')cout<<a+b<<endl;
else if(c=='-')cout<<a-b<<endl;
else if(c=='*')cout<<a*b<<endl;
else if(c=='/'){
if(a%b==0){
cout<<a/b<<endl;
}else{
cout<<fixed<<setprecision(2)<<double(a)/b<<endl;
}
}
}
return 0;
}

B#

Problem B: 整数翻转
主要在于如何判断溢出,这里采用了开long long类型的变量,通过比较大小判断是否溢出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
const int N=2147483647;
long long rev(long long x){
long long ans=0;
while(x){
ans=ans*10+x%10;
x/=10;
}
return ans;
}
int main(){
long long n;
while(cin>>n){
long long re=rev(n);
if(re>=(-N-1)&&re<=N)cout<<re<<endl;
else cout<<"0\n";
}
return 0;
}

C#

Problem C: 各位相加
按照题意模拟,把各个位上的数加起来,递归处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
int dig(int x){
if(x<10)return x;
int sum=0;
while(x){
sum+=x%10;
x/=10;
}
return dig(sum);
}
int main(){
int n;
while(cin>>n){
cout<<dig(n)<<endl;
}
return 0;
}

D#

Problem D: 整数转化为罗马数字
罗马数字看似复杂其实也有规律可循。
与普通数字一样可以按位处理。这里采用了常量字符串数组简化判断过程。
s[1]~s[9]对应罗马数字的1~9
s[11]~s[19]对应罗马数字的10~90
后面的以此类推。
注意0是没有对应的罗马数字的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string>
using namespace std;
string s[]={"0","I","II","III","IV","V","VI","VII","VIII","IX","0","X","XX","XXX","XL","L","LX","LXX","LXXX","XC","0","C","CC","CCC","CD","D","DC","DCC","DCCC","CM","0","M","MM","MMM"};
int main(){
string ss;
while(cin>>ss){
int len=ss.length();
for(int i=0;i<len;i++){
if(ss[i]!='0')cout<<s[(len-i-1)*10+ss[i]-'0'];
}
cout<<endl;
}
return 0;
}


E#

Problem E: 旋转数组

显然移动k次和移动k%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 <iostream>
using namespace std;
int main(){
int n;
while(cin>>n){
if(n==0)break;
int a[55];
for(int i=1;i<=n;i++){
cin>>a[i];
}
int k;
cin>>k;
k%=n;
for(int i=n-k+1;i<=n;i++)
cout<<a[i]<<' ';
for(int i=1;i<=n-k;i++){
cout<<a[i];
if(i==n-k)cout<<endl;
else cout<<' ';
}
}
return 0;
}


F#

Problem F: Zigzag表示
此题可以找规律发现输出字符串下标的关系。
具体过程就不在此细说了。
注意运算过程中下标不要越界了。
下面程序在字符串末尾添加了大量空格,避免了特殊处理越界情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
using namespace std;
int main(){
string s;
int n;
while(cin>>s>>n){
for(int i=0;i<1000;i++)s+=" ";
int len=s.length();
for(int i=1;i<=n;i++){
for(int j=i-1;j<len;j+=(n-1)*2){
if(s[j-(i-1)*2]!=' '&&i!=n&&j-(i-1)*2>=n&&j-(i-1)*2!=j)cout<<s[j-(i-1)*2];
if(s[j]!=' ')cout<<s[j];
}
}
cout<<endl;
}
return 0;
}


C+#

这里给出C题另外一种做法,巧妙的利用了求余与数位的性质。
在此就不给出推导过程与证明了。

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
int main(){
int n;
while(cin>>n){
if(n==0)cout<<"0\n";
else cout<<(n+8)%9+1<<endl;
}
return 0;
}


2018级计科1、计科2、网工、信安班第14周竞赛题题解

https://blog.tootal.xyz/posts/2018cs-w14c/

作者

黄智权

本文发布于

2018-12-03

本文更新于

2018-12-03

许可协议

评论