【GDKOI】2021普及Day2

【GDKOI】2021普及Day2

第一题 初中生数学题

提交文件: math.cpp
输入文件: math.in
输出文件: math.out
时间空间限制: 1s, 512MB
你已经上初中了,相信你一定会做这道题。
给定 10 个正整数,记为 a1, a2, a3, · · · , a10。 令 x = 1a1 × 2a2 × 3a3 × · · · × 10a10。 求 x 在 10 进制下从低位到高位的第一个非 0 位上的数字是多少。

输入格式

一行,10 个非负整数,分别表示 a1, a2, a3, · · · , a10。

输出格式

一行,一个非负整数,表示第一个非 0 位上的数字是多少。

样例数据

math.in
1 2 1 0 2 1 0 0 0 3
math.out
8

样例解释

1 × 22 × 3 × 52 × 6 × 103 = 1800000

数据范围

对于 30% 的数据,保证
∑i=1~10, ai ≤ 9。
对于另外 20% 的数据,保证除 a2 和 a5 外,其他数字全部为 0。
对于 100% 的数据,保证 ai ≤ 105

代码

#include<iostream>
#include<cstdio>
using namespace std;
long long a[110];
int main()
{
    
    
	long long i;
	long long ans=1;
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
	for(i=1;i<10;i++)
		scanf("%lld",&a[i]);
	a[2]+=a[6]+(a[4]<<1)+(a[8]<<1)+a[8];
	a[3]+=a[6]+(a[9]<<1);
	a[4]=a[6]=a[8]=0;
	if(a[2]>a[5]) for(i=a[2]-a[5];i;ans=(ans<<1)%10,i--);
	else for(i=a[5]-a[2];i;ans=(ans*5)%10,i--);
	for(i=0;i<a[3];ans=ans*3%10,i++);
	for(i=0;i<a[7];ans=ans*7%10,i++);
	printf("%lld",ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

第二题 二叉树

提交文件: tree.cpp
输入文件: tree.in
输出文件: tree.out
时间空间限制: 3s, 512MB
给定一颗搜索二叉树的 BFS 序,请判断该棵二叉树是否为正则二叉树。
下面是一些可能有用的定义:
正则二叉树 一颗有根二叉树,满足每个节点要么是叶子节点,要么一定有两个儿子。
搜索二叉树 一颗有根二叉树,满足任意一个节点 k,k 左子树的任一节点的权值小于等于节点 k 的权值,k
右子树的任一节点的权值大于等于节点 k 的权值。
二叉树的 BFS 序 以离根节点的距离为顺序进行遍历。其中,将子节点加入队列时,左侧儿子节点优先级高
于右侧儿子节点。

输入格式

输入包含多组测试数据。
第一行一个整数 T,表示该测试点所包含的数据组数。
对于每组测试数据,
第一行一个整数 n,表示搜索二叉树的节点个数。
第二行给出一个大小为 n 的排列,表示搜索二叉树的 BFS 序。
本题输入输出量较大,请使用较快的输入输出方式。

输出格式

共 T 行,每行输出 YES 或 NO,表示该棵搜索二叉树是否正则二叉树.

样例数据

tree.in
25
2 1 4 3 5
5
3 2 4 1 5
tree.out
YES
NO

数据范围

对于 30% 的数据, 保证 T ≤ 100, n ≤ 500。
对于 60% 的数据, 保证 T ≤ 100, n ≤ 5 × 103。
对于 100% 的数据, 保证 T ≤ 100, n ≤ 105。

代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
struct t
{
    
    
	int l,r,s;
};
t tree[4000010];
int c,mx,tot,x,mxs;
queue<int> que,que_;
void inserttree(int w)
{
    
    
	if(tree[tot].s<=tree[w].s) 
		if(tree[w].l==0)
			tree[w].l=tot;
		else
			c++,inserttree(tree[w].l);
	else
		if(tree[w].r==0)
			tree[w].r=tot;
		else
			c++,inserttree(tree[w].r);
	return;
}
bool BFS()
{
    
    
	int tem;
	que=que_;
	for(que.push(1);!que.empty();que.pop())
	{
    
    
		tem=que.front();
		if((tree[tem].l>0)^(tree[tem].r>0)) return 0;
		else if((tree[tem].l>0)&&(tree[tem].r>0)) que.push(tree[tem].l),que.push(tree[tem].r);
	}
	return 1;
}
int main()
{
    
    
	int T,i,n;
	t tem;
	tem.l=tem.r=tem.s=0;
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	for(scanf("%d",&T);T;T--)
	{
    
    
		scanf("%d",&n);
		for(i=1;i<=n;i++)
			tree[i]=tem;
		if(n==0)
		{
    
    
			printf("NO\n");
			for(i=0;i<n;scanf("%*d"),i++);
		}
		else 
		{
    
    
			tot=1;
			scanf("%d",&tree[1].s);
			mxs=tree[1].s;
			for(mx=1,i=1;i<n;i++)
			{
    
    
				scanf("%d",&tree[++tot].s);
				c=2;
				inserttree(1);
				if(c>mx)
				{
    
    
					mx=c;
					mxs=tree[tot].s;
				}
				else
				{
    
    
					if(c==mx)
					{
    
    
						if(tree[tot].s<mxs)
						{
    
    	
							printf("NO\n");
							for(i++;i<n;scanf("%*d"),i++);
						}
						else
							mxs=tree[tot].s;
					}
					else
					{
    
    	
						printf("NO\n");
						for(i++;i<n;scanf("%*d"),i++);
					}
				}
			}
			if(i==n)
				if(BFS()) 
					printf("YES\n");
				else 
					printf("NO\n");
			else;
		}
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

第三题 我的世界

提交文件: minecraft.cpp
输入文件: minecraft.in
输出文件: minecraft.out
时间空间限制: 1s, 512MB
众所周知,在我的世界这个游戏中具有主世界以及下界两个世界,主世界与下界存在一定的关系。具体
来说,主世界的水平坐标与下界的水平坐标为 8 : 1。也就是说,在下界移动 1 个单位的距离,相当于主世界
移动 8 个单位的距离。
在得知这个规律后,小 A 希望通过这个方法迅速到达自己想去的地方。在小 A 的世界中,小 A 探索过
的地方可以用一棵 n 个节点的树来表示(即:主世界和下界都是这样的一棵树)。我们用 (x, y, w) 表示树上
一条双向边,表示在下界中走过这条边需要 w 的时间,在主世界中走过这条边需要 8w 的时间。虽然在下界
可以快速移动,但我们需要通过下界传送门来到达下界或者回到主世界,在主世界的节点 i 使用一次下界传
送门可以到达下界的节点 i,在下界的节点 i 使用一次下界传送门可以回到主世界的节点 i,二者花费的时间
都是 ai。
现在小 A 有 q 个行动计划,每个计划希望从主世界的 x 节点到达主世界的 y 节点。因为地图上有各种
各样的怪物,所以小 A 希望知道在通过尽量少的节点的前提下,每个计划最少需要多少时间?

输入格式

第一行一个整数 n,表示树的节点数。
第二行 n 个整数,第 i 个整数 ai 表示节点 i 使用一次下界传送门需要花费的时间。
接下来 n 1 行,每行三个整数 x, y, w,表示树上的一条双向边。
接下来一行,一个整数 q,表示行动计划的数量。
接下来 q 行,每行两个整数 x, y,表示行动计划的起始节点和目标节点。

输出格式

输出 q 行,每行一个整数,表示行动计划最少需要的时间。
样例数据
minecraft.in
5
17 3 19 7 9
1 3 3
3 4 1
1 2 1
4 5 1
5
1 4
1 2
3 5
2 4
2 5
minecraft.out
28
8
16
15
18

数据范围

对于 40% 的数据,n, q ≤ 5000。
对于所有数据,n, q ≤ 2 × 105, 1 ≤ x, y ≤ n, 0 < ai, w ≤ 109。

代码

用LCA。
错误代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
int a[1010][1010],b[1010][1010];
bool d[1010];
int main()
{
    
    
	int i,j,n;
	freopen("matrix.in","r",stdin);
	freopen("matrix.out","w",stdout);
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(d,0,sizeof(d));
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	for(i=1;i<=n;i++)
	{
    
    
		for(j=1;j<=n;j++)
		{
    
    
			if(a[i][j]==2)
				b[i][j]=1,d[j]=1,j=n;
			if(a[i][j]==1)
				if(!d[j])
					b[i][j]=1,d[j]=1,j=n;
		}
	}
	for(i=1;i<=n;putchar('\n'),i++)
		for(j=1;j<=n;j++)
			printf("%d ",b[i][j]);
	for(i=1;i<=n;putchar('\n'),i++)
		for(j=1;j<=n;j++)
			printf("%d ",a[i][j]-b[i][j]);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

第四题 矩阵

提交文件: matrix.cpp
输入文件: matrix.in
输出文件: matrix.out
时间空间限制: 1s, 512MB
有一个 n × n 的矩阵 A,令 ri 表示 A 的第 i 行的元素的和,cj 表示 A 的第 j 列的元素的和。
A 是一个特殊的矩阵,满足所有 ri 以及 cj 都是偶数。
现在要将 A 分成两个矩阵,即求 n × n 的矩阵 B 和 C 满足
A = B + C B 和 C 的元素都是非负整数,且对于任意 1 ≤ i ≤ n,B 的第 i 行的元素和等于 C 的第 i 行的元素和;
对于任意 1 ≤ j ≤ n,B 的第 j 列的元素和等于 C 的第 j 列的元素和。

输入格式

第一行一个整数 n。
接下来 n 行,每行 n 个整数,表示矩阵 A。

输出格式

输出 2n 行,每行 n 个数字,前 n 行表示矩阵 B,后 n 行表示矩阵 C。
注:样例输出为了更易读,在矩阵之间增加了一个空行,选手在答题时无需输出空行。

样例数据

matrix.in
3
1 8 7
5 6 3
2 4 0
matrix.out
0 3 5
2 5 0
2 1 0
1 5 2
3 1 3
0 3 0

数据范围

对于所有数据,n ≤ 1000, 0 ≤ Aij ≤ 109。
对于 30% 的数据,n ≤ 100;
对于另外 20% 的数据,0 ≤ Aij ≤ 1;
对于另外 20% 的数据,A 每行每列的和都是 2。

代码

错误:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
int a[1010][1010],b[1010][1010];
bool d[1010];
int main()
{
    
    
	int i,j,n;
	freopen("matrix.in","r",stdin);
	freopen("matrix.out","w",stdout);
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(d,0,sizeof(d));
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	for(i=1;i<=n;i++)
	{
    
    
		for(j=1;j<=n;j++)
		{
    
    
			if(a[i][j]==2)
				b[i][j]=1,d[j]=1,j=n;
			if(a[i][j]==1)
				if(!d[j])
					b[i][j]=1,d[j]=1,j=n;
		}
	}
	for(i=1;i<=n;putchar('\n'),i++)
		for(j=1;j<=n;j++)
			printf("%d ",b[i][j]);
	for(i=1;i<=n;putchar('\n'),i++)
		for(j=1;j<=n;j++)
			printf("%d ",a[i][j]-b[i][j]);
	fclose(stdin);
	fclose(stdout);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46975572/article/details/115371803
今日推荐