第一次额外作业 题解
1. 斐波那契
出题思路:
(对于此前不知道斐波那契数列的同学)考察递推公式的理解能力。考察基本的输出语法。
解题思路:
使用cout
直接输出即可。
AC代码:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
cout<<"0 1 1 2 3 5 8 13 21 34"<<endl;
return 0;
}
2.一群奇怪的人
出题思路:
读题能力+数学思维。
解题思路:
本题突破点在于倒数第二句:
把西瓜分成两部分,每部分的重量都是偶数,同时,这两部分不能是相等的。
我们知道,除了2以外的任何偶数均可以分成两个不相等的偶数。所以只需判断输入的内容是否是除2以外的偶数。
AC代码:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int n;
cin>>n;
if(n!=2){//判断是不是等于2
if(n%2==0){//判断是不是为偶数
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}else{
cout<<"NO"<<endl;
}
return 0;
}
3.取钱
出题思路:
取模、整除运算的使用。
解题思路:
依次计算——先算1w元的张数,然后去掉这一部分;再计算5k元的张数,去掉这一部分;……
AC代码1:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int n,ans=0;
cin>>n;
ans=ans+n/10000;//计算1w元的张数
n=n%10000;
ans=ans+n/5000;//计算5k元的张数
n=n%5000;
ans=ans+n/2000;//计算2k元的张数
n=n%2000;
ans=ans+n/1000;//计算1k元的张数
n=n%1000;
ans=ans+n/500;//计算500元的张数
n=n%500;
ans=ans+n/100;//计算100元的张数
n=n%100;
ans=ans+n/50;//计算50元的张数
n=n%50;
ans=ans+n/10;//计算10元的张数
n=n%10;
ans=ans+n/5;//计算5元的张数
n=n%5;
ans=ans+n/1;//计算1元的张数
n=n%1;
cout<<ans<<endl;
return 0;
}
AC代码2:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int n;
cin>>n;
cout<<n/10000 + n%10000/5000 + n%10000%5000/2000 + n%10000%5000%2000/1000 + n%10000%5000%2000%1000/500 + n%10000%5000%2000%1000%500/100 + n%10000%5000%2000%1000%500%100/50 + n%10000%5000%2000%1000%500%100%50/10 + n%10000%5000%2000%1000%500%100%50%10/5 + n%10000%5000%2000%1000%500%100%50%10%5/1;
return 0;
}
4.茴香豆
出题思路:
高斯公式: \(1+2+…+n=\frac{(1+n)*n}{2}\) 。
等差数列求和:\(n*a_1+\frac {n*(n-1)*d}{2}\) 。
解题思路:
本题的关键在于弄清楚三个变量分别代表什么。
容易计算: \(w\) 碟茴香豆价格为 \(S=k+2*k+3*k+…+i*k\) 。有两个数学公式可解此式。
当 \(S\geq n\) 时,说明不需要借钱;反之,则需要向室友借 \(S-n\) 元。
AC代码1:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int k,n,w,S;
/*k:单价
n:余额
w:购买数量*/
cin>>k>>n>>w;
S=(k+w*k)*w/2;//高斯公式
if(S<n){
cout<<"0"<<endl;
}else{
cout<<S-n<<endl;
}
return 0;
}
AC代码2:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int k,n,w,S;
/*k:单价
n:余额
w:购买数量*/
cin>>k>>n>>w;
S=w*k+w*(w-1)*k/2;//等差数列求和公式
if(S<n){
cout<<"0"<<endl;
}else{
cout<<S-n<<endl;
}
return 0;
}
5.+1!再+1!
出题思路:
整除运算的使用。
解题思路:
本题应当讨论三种情况:
-
若 \(a\%b=0\) ,则无需操作,直接输出 \(0\) 即可。
-
若 \(a > b\) ,只需要找到比 \(a\) 大的第一个 \(b\) 的倍数。稍加推理,可得到这一式子: \((a/b+1)*b\) (注意,这里的除号代表整除)。
-
若 \(a\leq b\) ,显然的,要使得 \(a\) 能被 \(b\) 整除,只需要让 \(a=b\) 。
AC代码:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
if(a%b==0){
cout<<0<<endl;
}else if(a<b){
cout<<b-a<<endl;
}else{
cout<<(a/b+1)*b-a<<endl;
}
return 0;
}
6.走寝
出题思路:
多重选择语句、嵌套选择语句的使用。
解题思路:
首先考虑队友说谎情况:
- 题目告诉我们,队友的寝室为奇数,故读入偶数则直接Dame。
- 题目第一句提了一嘴,队友不在123寝室,故读入123则直接Dame。
再计算队友寝室与WIDA寝室间隔距离。因为寝室号都是奇数,只需相减后除2即可。
最后考虑移动的情况,这里其实与第三题《取钱》类似,先计算走到队友寝室需要多少个5步(使用整除),再计算是否已经到达(使用取模)。
AC代码:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int x,ans;
cin>>x;
if(x%2==0){
cout<<"Dame";
}
else if(x==123){
cout<<"Dame";
}else{
if(x-123<0){//队友在123寝室左边
x=123-x;
}else{//队友在123寝室右边
x=x-123;
}
x=x/2;
ans=x/5;
if(x%5==0){
cout<<ans<<endl;
}else{
cout<<ans+1;
}
return 0;
}
return 0;
}
7.奇怪的人
出题思路:
数学证明
解题思路:
以下内容其实很好证:
-
对于两个数字 \(a=b\) 并且等于 \(0\) ,即为答案。
-
对于两个数字 \(a=b\) 并且不等于 \(0\) ,只需要一个步骤,即可得到 \(0\ 0\) 。
- 同时对 \(a\) 和 \(b\) 加上 \(-(a)\) 。
-
对于两个数字 \(a > b\) ,若 \(a+b\) 是偶数,一定存在 \(t=\frac {a+b}{2}\) ,使得 \(a-t=a-\frac {a+b}{2}=\frac {a-b}{2}\) ,同理, \(b-t=b-\frac {a+b}{2}=\frac {b-a}{2}\) ,即,使得 \(a-t=-(b-t)\) 成立。需要两个步骤,即可得到 \(0\ 0\) 。
- 同时对 \(a\) 和 \(b\) 加上 \(-t\) 。
- 同时对 \(a\) 和 \(b\) 加上 \(-(a-t)\) 。
-
其他所有情况均无法得到 \(0\ 0\) 。
AC代码:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int x,y,t;
cin>>x>>y;
if(x<y){
t=x;
x=y;
y=t;
}
if(x==0 && y==0){
cout<<0<<endl;
}else if(x==y){
cout<<1<<endl;
}else if((x-y)%2==0){
cout<<2<<endl;
}else{
cout<<-1<<endl;
}
return 0;
}
8.无限之路
解题思路:
答案由四部分组成:
- 位于 \(pos\) 号路灯之后的,编号为偶数的路灯,满足方程: \(\frac{x}{2} \leqslant pos\) 。
- 位于 \(pos\) 号路灯之前的,编号为偶数的路灯,满足方程: \(x\geqslant pos+1\) 。
- 位于 \(pos\) 号路灯之后的,编号为奇数的路灯,满足方程: \(x\leqslant pos\) 。
- 位于 \(pos\) 号路灯之前的,编号为奇数的路灯,满足方程: \(3*x+1\geqslant pos+1\) 。
于是题目化简为求满足\(\begin{cases} pos+1\leqslant x\leqslant 2*pos & \text{ x为偶数 } \\ pos\leqslant 3*x\leqslant 3*pos & \text{ x为奇数 } \end{cases}\)的 \(x\) 的数量。
由简单数理推断,发现当 \(pos\) 为偶数时,答案为 \(\frac{pos}{2}+(pos-2)/3+1\) ;当 \(pos\) 为奇数时,答案为 \(\frac{pos+1}{2}+pos/3+1\) (注意,这里的除号代表整除)。
AC代码:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int q,pos,ans=0;
cin>>pos;
if(pos%2==0){
ans+=pos/2;
ans+=(pos-2)/3+1;
}else{
ans+=(pos+1)/2;
ans+=pos/3+1;
}
cout<<ans<<endl;
return 0;
}
9.普通的一天
解题思路:
分析可得:
- 任取两个顶点,可以连出一根直线。
- 任取两根直线,可以得到一个交点。
所以,在 \(n\) 边形的所有顶点中,任取四个,都可以得到一个交点。本题转化为有多少种顶点取法,借助组合数学的知识,答案为 \(C^4_n\) 。
AC代码:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int n;
cin>>n;
cout<<n*(n-1)*(n-2)*(n-3)/24;
return 0;
}
10.n芒星图
解题思路:
由连续曲线反射规律——入射光线与出射光线关于入射点在曲线上切线夹角相等可知,从 \(A_0\) 射出,朝向 \(A_p\) ,经反射后必定朝向 \(A_{2*p}\) ,同理,经过 \(k\) 次反射后,必定朝向 \(A_{k*p}\) 。而因为是一个圆,故需要再对 \(k*p\) 取一次模。
AC代码:
//Edited and produced by WIDA
#include <iostream>
using namespace std;
int main(){
int n,p,k,t=0;
cin>>n>>p>>k;
t=(p*k)%n;
cout<<t<<endl;
}