初二普及组全真模拟赛 题解

数你太美【第一周】

题目描述

PB 获得了两个正整数数列 a i {a_i} ai , b i {b_i} bi ,长度分别为 n , m ,其中每个数都小于 10。 定义一个正整数是“美丽的正整数”,当且仅当:这个数的十进制表示中,至少有一个 数位上的数在数列 a_i 出现过,至少有一个数位上的数在数列 b_i 出现过。现在 PB 希 望求出最小的“美丽的正整数”。

输入格式

第一行,两个正整数 n , m ;

第二行,n 个正整数,第 i 个为 a_i ;

第三行,m 个正整数,第 i 个为 b_i 。

输出格式

一行,一个正整数表示最小的“美丽的正整数”。

样例
样例输入
样例输入 1

2 3
2 4
6 5 2

样例输出 1

2

样例解释 1

2 既在数列 a 中出现又在数列 b 中出现,且可知没有比 2 小的正整数是“美丽的正整 数”。

样例输入 2

2 6
8 7
1 1 4 5 1 4

样例输出 2

17

样例解释 2:

17 中有数位 1,7 。1 在数列 b 中出现, 7 在数列 a 中出现,且可以证明没有比 17 小 的正整数是“美丽的正整数”。

数据范围与提示

对于 30% 的数据, 1 < = n , m < = 4 ; 1<=n,m<=4; 1<=n,m<=4;
对于 100% 的数据, 1 < = n , m < = 9 , 1 < = a i , b i < = 9 。 1<=n,m<=9,1<=a_i,b_i<=9。 1<=n,m<=9,1<=ai,bi<=9

分析

首先已知所有的 a i a_i ai b i b_i bi都不会大于9,则可知道组合的“美丽的正整数”一定没有单独的“美丽的正整数”优。
不难想出方法,先排序,遍历两个数组,如果有相同元素,则直接输出并退出,否则就比较两个序列的最小值,将其组成两位数输出。

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 105;
const int INF = 0x3f3f3f3f;

int n, m, a[MAXN], b[MAXN], ans;
bool flag;

int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    for (int i = 1; i <= m; i++) {
        scanf("%d", &b[i]);
    }
    sort(a + 1, a + 1 + n);
    sort(b + 1, b + 1 + m);
    ans = 0x3f3f3f3f;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (a[i] == b[j]) {
                ans = min(ans, a[i]);
                flag = 1;
            }
        }
    }
    if (flag)
        printf("%d\n", ans);
    else {
        printf("%d%d\n", min(a[1], b[1]), max(a[1], b[1]));
    }
    return 0;
}

逃亡【第一周】

题目描述

从前有个平面直角坐标系,坐标系里有座学校。这是一个矩形,左下角是 (0,0),右上角是 (n,m)。有 k 个蒟蒻在校园中。第 i 个蒟蒻在 (xi,yi) 的位置。由于一些不可 抗因素,所有 xi 互不相同,所有 yi 互不相同。这时 PB 要来抓蒟蒻们做实验了!

蒟蒻们听到这个消息,也是四处逃亡,只要逃到校园的边界上就不会被 PB 抓到。 每个蒟蒻可以沿着任意路线逃亡。然而蒟蒻们反应迟钝,所以如果两个蒟蒻的逃亡路线 有交点,它们就有可能相撞,就会被 PB 抓住。所以任意两人的路线不能有交点。

现在蒟蒻们想知道,蒟蒻全部能成功逃亡的路线的长度之和的最小值。(虽然,这 对神通广大的 PB 根本不是一回事…)

输入格式

第一行三个整数 n, m, k,相邻两数用一个空格分开。

接下来 k 行,第 i 行两个正整数 xi 和 yi,用一个空格分开。

输出格式

一行一个数表示总距离的最小值,保留 3 位小数。

样例
样例输入

5 5 1
1 2

样例输出

1.000

数据范围与提示

对于前 30% 的数据,0<=n,m<=6, 1<=k<=5。

对于前 100% 的数据,0<=n,m<=10^9, 1<=k<=5000, 1<=xi<n, 1<=yi<m

对于所有数据,xi 互不相同,yi 互不相同。

分析

开始读题有点晕,准备想如何分配每个蒟蒻的逃跑路线,但画图后我发现 “任意两人的路线不能有交点。”是一句废话。
假设有一个点 ( x , y ) (x, y) (x,y),那么在不考虑其他点的情况下,它的最优逃跑路线就是它分别到四个边界的距离的最小值即 M i n ( x , y , n − x , n − y ) Min(x, y, n - x, n - y) Min(x,y,nx,ny)。并且此题也不需要考虑其他点

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 5005;

int n, m, k, x, y;
double ans;

int main() {
	scanf ("%d %d %d", &n, &m, &k);
	for (int i = 1; i <= k; i++) {
		scanf ("%d %d", &x, &y);
		x = min(x, n - x);
		y = min(y, m - y);
		ans += min(x, y);
	}
	printf ("%.3lf\n", ans);
	return 0;
} 

数数字【第一周】

题目描述

PB 带来了若干只蒟蒻。

众所周知,NTF 是数论学会的会长,于是 PB 准备用数字击败 NTF,以证明 PB 比 NTF 更强。

于是 PB 准备了一些卡片,并在每个蒟蒻头上都贴了一张卡牌。每个卡牌上都写了一个数字。

由于蒟蒻太弱了,甚至不会看镜子来了解自己头上的数字,但他们由于经常被大佬吊打,所以观察力敏锐,他们都知道别人头上的数字。

第 i 个蒟蒻会告诉你他看到了 ai 种数字(定义两个数字不同种当且仅当它们的值不同)

但是由于蒟蒻太弱了,可能会报错数据,NTF 需要核实是否有一种情况使所有蒟 蒻说的话都正确。(可能情况不唯一)

输入格式

多组测试,文件第一行一个整数 T,表示测试数据组数;

对于每组数据,第一行,一个整数 n,表示蒟蒻的数量;

第二行,n 个整数用空格隔开,表示数组 ai,意义同题面。

输出格式

如果至少有一种情况使所有蒟蒻的话都正确,输出"yes",否则,输出"no"。

样例
样例输入

2
2
1 1
4
1 3 2 2

样例输出

yes
no

数据范围与提示

对于所有数据,T<=10

对于 20% 的数据,N≤8

对于所有数据,1≦N≤1000000, 0≦ai<N

分析

一道思维题。
考试时先打了一个假暴力,考完看提交记录有50pts,然后开始想数学解法。
打假暴力时想到了一个优化:如果这个数列中最大值与最小值已经相差了2及以上,就不用管了。
因为每个蒟蒻看到的种数是 a i a_i ai, 那么总种树无非就是 a i + 1 a_i +1 ai+1(自己头上的数字唯一)或者 a i a_i ai(自己头上的数字不唯一,已经出现过),当两个 a i a_i ai相差2及以上是,是无论如何也无法匀平的。
继续按思路往下走,当最大值和最小值不同时,就只有两种情况,相差一或相等。

当最大值等于最小值的时候,分两种情况讨论,最大值等于 n − 1 n-1 n1说明所有的蒟蒻的数字都是唯一的,符合条件。如果最大值的二倍小于 n n n,也满足条件,因为每个每个蒟蒻都不唯一,所以至少有两个蒟蒻的数字一样,则他们可以互相看到,可以弥补上统计,正是如此,那么也可以得知此时每个数字都有两个重复的元素,所以最大值的二倍要小于 n n n.

那么当他们相差一的时候,就说明有蒟蒻头上的数字唯一(因为蒟蒻无法看到自己头上的数字,所以会统计掉一个,但其他头上是重复数字的蒟蒻则会把他统计上,导致相差一),用一个 s u m sum sum统计有多少个数字唯一的蒟蒻(即 a i = M i n ( a 1 . . . a n ) a_i=Min(a_1 ... a_n) ai=Min(a1...an)),可得 s u m sum sum应该大于 M i n ( a 1 . . . a n ) Min(a_1 ... a_n) Min(a1...an),因为已经得到了最大值与最小值相同时的结论,我们可以在现在的数列中去掉数字唯一的蒟蒻,那么最大值应该小于等于 ( n − s u m ) / 2 + s u m (n - sum) / 2 + sum (nsum)/2+sum

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1000005;
const int INF = 0x3f3f3f3f;

int t, n, t1, t2, sum;
int a[MAXN];

int main() {
	scanf ("%d", &t);
	while (t--) {
		scanf ("%d", &n);
		t1 = INF;
		t2 = -1;
		sum = 0;
		for (int i = 1; i <= n; i++) {
			scanf ("%d", &a[i]);
			t1 = min(t1, a[i]);
			t2 = max(t2, a[i]);
		}
		if (t2 - t1 > 1) {
			printf ("no\n");
			continue;
		}
		if (t2 - t1 == 1) {
			for (int i = 1; i <= n; i++) {
				if (a[i] == t1) {
					sum ++;
				}
			}
			if (sum < t2 && t2 <= (n - sum) / 2 + sum) {
				printf ("yes\n");
				continue;
			} else {
				printf ("no\n");
				continue;
			}
		}
		if (t2 == t1) {
			if (t2 == n - 1) {
				printf ("yes\n");
				continue;
			} 
			if (t2 * 2 <= n) {
				printf ("yes\n");
				continue;
			} else {
				printf ("no\n");
				continue;
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值