上海市青少年算法2021年8月月赛(丙组)

T1 阅读竞赛
题目描述
小爱和小艾在比赛谁看的书多。截止今日,小爱读了 a 本书,小艾同学读了 b 本书,小爱想要通过每天更多一点的努力,在阅读量上超越小艾。
为此,小爱决定每天读 x 本书,而小艾每天读 y 本书,请问几天后小爱的做题量会超越小艾。若不可能超过,输出 Impossible。
输入格式
输入第一行两个正整数,表示a,b。
输入第二行两个正整数:表示x,y。
输出格式
输出小爱的阅读量超越小艾所需的天数。
数据范围
1≤a,b≤1000
1≤x,y≤10
样例数据
输入:
4 10
3 1
输出:
4
说明:
3天后,小爱4+3*3=13,小艾10+1*3=13
4天后,小爱4+3*4=16,小艾10+1*4=14,小爱超过了小艾
输入:
10 9
1 1
输出:
0
说明:
一开始就超过了小艾
输入:
9 10
1 1
输出:
Impossible

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
	long long a,b,x,y,t;
	cin>>a>>b>>x>>y;
	if(a>b)cout<<0;
	else{
		if(x<=y)cout<<"Impossible";
		else {
			t=ceil(1.0*(b-a)/(x-y));
			if(t==(b-a)/(x-y))cout<<t+1;
			else cout<<t;
		}
	}
    return 0;
}

T2 罗马数字
题目描述
罗马数字采用十进制,1 到 9 的表示方法分别为
I, II, III, IV, V, VI, VII, VIII, IX
10 到 90 的表示分别为
X, XX, XXX, XL, L, LX, LXX, LXXX, XC
100 到 900 的表示分别为
C, CC, CCC, CD, D, DC, DCC, DCCC, CM
1000 到 3000 的表示方法分别为
M, MM, MMM
更大的数字就不再解释了。
对于一个十进制的数,将它的每位数字写成罗马数字,拼接在一起,就得到了这个数的罗马数字。如XXX=30,CCXVIII=218,MI=1001,CDXX=420,CDIV=404等。
给定一个 n,请输出它所对应的罗马数字。
输入格式
第一行:单个整数n
输出格式
第一行:若干字符表示n的罗马数字
数据范围
1≤n<4000
样例数据
输入:
19
输出:
XIX
输入:
22
输出:
XXII
输入:
99
输出:
XCIX

#include <iostream>
#include <cstdio>
#include <cmath>//, , 
using namespace std;
string a1[10]={"0","I","II","III","IV","V","VI","VII","VIII","IX"};
string a10[10]={"0","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"};
string a100[10]={"0","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"};
string a1000[4]={"0","M","MM","MMM"};
int main()
{
	int n;
	string s="";
	cin>>n;
	if(n>0) {if(n%10!=0) s=a1[n%10]+s;n/=10;}
	if(n>0) {if(n%10!=0) s=a10[n%10]+s;n/=10;}
	if(n>0) {if(n%10!=0) s=a100[n%10]+s;n/=10;}
	if(n>0) {if(n%10!=0) s=a1000[n%10]+s;n/=10;}
	cout<<s<<endl;
    return 0;
}

T3 四方定理
题目背景
四方定理是数论中著名的一个定理,指任意一个自然数都可以拆成四个自然数的平方之和。例如:
25 = 1^2 + 2^2 + 2^2 + 4^2
对2525来说,还有其他方案:
25 = 0^2 + 0^2 + 3^2 + 4^2
以及
25 = 0^2 + 0^2 + 0^2 + 5^2
题目描述
给定一个自然数 n,请输出 n 的所有四平方拆分方案。
输入格式
单个整数:表示 n。
输出格式
若干行:每行四个由小到大排列的自然数,表示一种拆分方案。如果有多种方案,先输出首项较小的方案,对于首项相同的方案,先输出第二项较小的方案,其他情况以此类推。
数据范围
0≤n≤50,000。
样例数据
输入:
25
输出:
0 0 0 5
0 0 3 4
1 2 2 4

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
struct abcd{
	int a,b,c,d;
}f[50005];
bool mycmp(abcd a,abcd b){
	if(a.a==b.a){
		if(a.b==b.b){
			if(a.c==b.c){
				return a.d<b.d;
			}
			return a.c<b.c;
		}
		else return a.b<b.b;	
	}
	else return a.a<b.a;
}
int main()
{
	int n,t=0;
	cin>>n;
	for(int d=sqrt(n);d>=sqrt(n)/2;d--)
		for(int c=d;c>=0;c--)
			for(int b=c;b>=0;b--){
				int a=sqrt(n-b*b-c*c-d*d);
				if(a*a==(n-b*b-c*c-d*d)&&a<=b){
					f[t].a=a;f[t].b=b;f[t].c=c;f[t].d=d;t++;
				}
			}
	sort(f,f+t,mycmp);
	for(int i=0;i<t;i++)
		printf("%d %d %d %d\n",f[i].a,f[i].b,f[i].c,f[i].d);	
    return 0;
}

T4 栈的判断
题目描述
给定 n 个数字,已知这些数字的入栈顺序为 1,2,⋯,n,给定一个出栈顺序 a1,a2,⋯,an,请判断它是否是一个合法的出栈顺序。
输入格式
第一行:单个整数 n;
第二行:n 个整数表示 a1,a2,⋯,an 
输出格式
如果合法,输出 Valid,否则输出 Invalid
数据范围
对于 30% 的数据,1≤n≤20;
对于 60% 的数据,1≤n≤2,000;
对于 100% 的数据,1≤n≤100,000;
样例数据
输入:
5
4 5 3 2 1
输出:
Valid
说明:
1 入栈
2 入栈
3 入栈
4 入栈
4 出栈
5 入栈
5 出栈
3 出栈
2 出栈
1 出栈
输入:
5
4 5 3 1 2
输出:
Invalid

#include <iostream>
#include <cstdio>
#include <cmath>
#include <stack>
using namespace std;
stack<int> s;
int main()
{
	int n,m,i,j=1;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d",&m);
		if(s.empty()&&j<=m){
			while(j<m) s.push(j++);
			j++;
		}
		else if(s.top()==m) s.pop();	
		else if(s.top()<m){
			while(j<m) s.push(j++);
			j++;
		}
		else if(s.top()>m){
			cout<<"Invalid"<<endl;
			return 0;
		}	
	}
	if(s.empty()) cout<<"Valid"<<endl;
    return 0;
}

T5 子集和
题目描述
给定 n 个正整数:a1,a2,⋯,an,请从中找出一些数字,使得它们的和恰好等于一个给定的目标 t。
输入格式
第一行:两个正整数 n 与 t。
第二行:n 个正整数 a1,a2,⋯,an 
输出格式
若能满足条件输出 Yes,否则输出 No。
数据范围
1≤n≤20
1≤t≤10^8
1≤ai≤10^8
样例数据
输入:
5 10
2 3 4 5 6
输出:
Yes

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
queue<int> q;
int main()
{
	long long n,t,m,j=1;
	scanf("%lld %lld",&n,&t);
	q.push(0);
	for(int i=0;i<n;i++){
		scanf("%lld",&m);
		for(int k=j;k>=1;k--){
			long long a=q.front();
			q.pop();
			if(a+m==t){
				cout<<"Yes"<<endl;return 0;
			}
			else {
				q.push(a+m);q.push(a);
			}
		}
		j*=2;
	}
	cout<<"No"<<endl;
    return 0;
}
#include <iostream>
using namespace std;
long long a[21],sum=0,n,t;
bool b=false;
void solve(int k){
	if(k>n||b) return;
	if(sum==t){
		cout<<"Yes";b=true;return;
	}
	sum+=a[k];solve(k+1);
	sum-=a[k];solve(k+1);
}
int main(){
	cin>>n>>t;
	for(int i=0;i<n;i++) cin>>a[i];
	solve(0);
	if(!b) cout<<"No"<<endl;
	return 0;
}

Guess you like

Origin blog.csdn.net/lybc2019/article/details/121364155