第一次额外作业 题解

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\) 取一次模。

uTools_1632300919847.png

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;
}
posted @ 2021-12-08 20:26  hh2048  阅读(36)  评论(0编辑  收藏  举报