2019年南海区青少年信息学奥林匹克竞赛(小学甲组)

2019年南海区青少年信息学奥林匹克竞赛(小学甲组)

得分:460分,一等500 (我还是太菜了)

总结:主要是第5题太可惜了(才20分)

下次要理清思路,想好具体做法再做

(似乎历年都是5或6题考贪心)

A. 打印方阵

题目描述
下面这样的方阵很有规律,称为蛇形方阵。例如3×3的:

1 2 3

6 5 4

7 8 9

现在给定边长,输出相应的蛇形方阵。

输入格式
一个整数n,表示要输出n×n的蛇形方阵,1≤n≤100。

输出格式
n行,每行n个整数,空格隔开。

样例
样例输入 1
4
样例输出 1
1 2 3 4
8 7 6 5
9 10 11 12
16 15 14 13

直接暴力,没有细节。

#include<iostream>
#include<fstream>
#include<algorithm>
#include<cmath>

using namespace std;

int n;

int main()
{
    
    
	 cin>>n;
	 for(int i=1;i<=n;i++)
	 {
    
    
	 	if(i%2==1)
	 	{
    
    
	 		for(int j=(i-1)*n+1;j<=i*n;j++)
	 		cout<<j<<" ";
	 		cout<<endl;
	 	}
	 	if(i%2==0)
	 	{
    
    
	 		for(int j=i*n;j>=(i-1)*n+1;j--)
	 		cout<<j<<" ";
	 		cout<<endl;
	 	}
	 }
    return 0;
}

B. 分数减法

题目描述
小学数学
这样的分式运算我们都会。请编程计算两个分数相减的结果。

输入格式
第一行,两个整数a和b,表示一个分数abab,1≤a<b≤10000。

第二行,两个整数c和d,表示一个分数cdcd,1≤c<d≤10000。

输入数据保证计算结果为正。

输出格式
两个整数,表示结果。

提示:运算结果分式要约分。

样例
样例输入 1
4 7
1 3
样例输出 1
5 21

注意结果要约分

#include<iostream>
#include<fstream>
#include<algorithm>
#include<cmath>

using namespace std;

int z1,m1,z2,m2,a1,a2,k;

int main()
{
    
    
     cin>>z1>>m1>>z2>>m2;
	 for(int i=1;i<=m1;i++)
	 {
    
    
	 	if(i*m2%m1==0)
	 	k=i*m2;
	 } //防止int炸(不加也没有关系)
	 z1=z1*(k/m1);
	 z2=z2*(k/m2);
	 a1=z1-z2;
	 a2=k;
	 int i=2;
	 while(i<=a1)
	 {
    
    
	 	if(a1%i==0&&a2%i==0)
	    a1=a1/i,a2=a2/i;
	    else
	    i++;
	 }//约分
     cout<<a1<<" "<<a2;

    return 0;
}

C. 倒背如流

题目描述
黑板上老师写了一行N个正整数,老师要考同学们的倒背如流能力,让学生从右向左读这些数字,并求出他们的和。例如写了3个整数:123 45 60。结果是:06+54+321=381

输入格式
第一行,一个整数n,1≤n≤100。

第二行,n个正整数,每个正整数不超过1000000。

输出格式
一个整数。

样例
样例输入 1
3
123 45 60
样例输出 1
381

字符串比较方便

#include<iostream>
#include<fstream>
#include<algorithm>
#include<string>
#include<cmath>//pow函数

using namespace std;

int n;
long long ans;
string s;

int main()
{
    
    
     cin>>n;
     for(int e=1;e<=n;e++)
     {
    
    
     	cin>>s;
     	for(int i=s.size()-1;i>=0;i--)
     	{
    
    
     		int d=s[i]-'0';
     		ans=ans+pow(10,i)*d;
     	}
     }
     cout<<ans;
    return 0;
}

D. 集合的差

题目描述
有两个数列A和B,那些在A中出现但不在B中出现的数就称为集合A和集合B的差:A-B。例如:A={1,4,5,2,6},B={5,3,2,7},那么A-B={1,4,6}。

现在给你2个集合A和B,求A-B有多少个数。

输入格式
第一行,两个整数na和nb,表示集合A和集合B各有多少个整数,1≤na,nb≤10000;

第二行,na个不同的正整数,表示集合A里的数,每个正整数不超过10000;

第三行,nb个不同的正整数,表示集合B里的数,每个正整数不超过10000。

输出格式
一个整数,A-B里有多少数。

样例
样例输入 1
5 4
5 2 4 8 7
3 7 6 2
样例输出 1
3

数据范围与提示
样例说明:
A-B={5,4,8}。

数组统计不会超时,没有细节

#include<iostream>
#include<fstream>
#include<algorithm>
#include<string>
#include<cmath>

using namespace std;

int n,a[10005],b[10005],f,ans,m;

int main()
{
    
    
     cin>>n;
	 cin>>m;
     for(int i=1;i<=n;i++)
     {
    
    
     	cin>>f;
     	a[f]++;
     	ans++;
     }
     for(int i=1;i<=m;i++)
     {
    
    
     	cin>>f;
     	if(a[f]==1)
     	ans--;
     }
     cout<<ans;
     
    return 0;
}

E. 可表示的数

题目描述
有N个整数从左到右排成一行,如果某个数等于它前面的2个数的和,就称这个数是可以表示的数。问给定的数列里有多少个数是可以表示的数。

输入格式
第一行,一个整数N,表示数列有多少个整数,1≤N≤10000;

第二行,N个正整数,每个正整数不超过10000。

输出格式
一个整数,有多少可表示的数。

样例
样例输入 1
8
5 2 2 3 4 8 7 16
样例输出 1
3

数据范围与提示
样例说明:
4=2+2;8=5+3;7=3+4。

嗷嗷嗷 简直气死,好多细节,我想的太复杂啦!

原始代码:

#include<iostream>
#include<fstream>
#include<algorithm>
#include<string>
#include<cmath>

using namespace std;

int n,a[10005],f,ans;

int main()
{
    
    
     cin>>n;
     for(int i=1;i<=n;i++)
     {
    
    
     	cin>>f;
     	a[f]=i;
     }//这样只要一有重复的,数组就会被覆盖掉
     for(int i=1;i<=10000;i++)
     {
    
    
     	for(int j=1;j<=10000;j++)
     	{
    
    
     		if(a[i]!=0&&a[j]!=0&&a[i+j]!=0&&a[i+j]!=-1)
     		{
    
    
     			if(a[i]<=a[i+j]&&a[j]<=a[i+j])
     			{
    
    
     			   ans++;	
     			   a[i+j]=-1;
     			}
     		}
     	}
     }//当时的逻辑好清奇,我到现在也想不通当时为什么要这样写……
     cout<<ans;
    return 0;
}

AC代码:

#include<iostream>
#include<fstream>
#include<algorithm>
#include<string>
#include<cmath>

using namespace std;

int n,a[10005],c[20005],ans;

int main()
{
    
    
     cin>>n;
     for(int i=1;i<=n;i++)
     	cin>>a[i];
     for(int i=1;i<=n;i++)
     {
    
    
     	for(int j=1;j<=i-1;j++)//往前找,保证是前面两个
     	{
    
    
            c[a[i]+a[j]]=1;//防止出现多个加起来相同的数
     	}
		 ans=ans+c[a[i]];//如果有相同的数字,那它也会++,妙哉
     }//我觉得有点类似素数筛法
     cout<<ans;
    return 0;
}

好气哦~

F.叠罗汉

题目描述
农场的N头奶牛喜欢玩叠罗汉游戏,就是几头奶牛1头奶牛接着1头奶牛的站成一柱子形状。不过奶牛的力量不一样,用数值Ci表示第i头奶牛它的上面最多可以站多少头奶牛,问这些奶牛最少可以站成几个柱子形状。

输入格式:
第一行,1个整数N,表示有多少头奶牛,1≤N≤1000;

第二行,N个正整数Ci,表示这些奶牛的力量,0≤Ci≤1000。

输出格式:
一个整数,表示最少成几个“罗汉”。

样例
输入样例:
5
0 2 1 2 2
输出样例:
2

数据范围与提示
样例说明:
可以第1、第3、第2头奶牛从上向下叠罗汉;
第4、第5头奶牛叠罗汉。

#其实就是贪心,考试时也想到了,但做法太复杂了(做对了还好,但问题是没对啊!)。

基本思想,从大到小放。(基本都能想到)
但如果相同,到底放不放?
如果放,后面就有点亏
如果不放,做到最后还不放答案就错了(考试时一直再纠结)

所以,就不要考虑放不放的问题吧,直接从小到大,从上到下叠,能放就放,不能就随缘吧:D (这招是一个大神想出来的,好厉害,膜拜)

AC代码:

#include<iostream>
#include<fstream>
#include<algorithm>
#include<string>
#include<cmath>

using namespace std;

int n,f,ans,c[10005],k,d;

int main()
{
    
    
    //freopen("638.in","r",stdin);
	//freopen("638.out","w",stdout);
	 cin>>n;
	 for(int i=1;i<=n;i++)
	 {
    
    
	 	cin>>f;
	 	c[f]++; 
	 }
	while(k<n)
	{
    
    
		d=0;//要承受多少只
		ans++;
		for(int i=0;i<=1000;)//注意0
	    {
    
    
		    if(c[i]!=0&&i>=d)
		    {
    
    
		    	c[i]--;//考虑多只奶牛f相同
		    	k++;
		    	d++;
			}
			else
			i++;
	    }
	}
	cout<<ans;
	
    return 0;
}

ε=(´ο`*))) 这次考得好烂啊

猜你喜欢

转载自blog.csdn.net/yyh0910/article/details/115056373