「Solution」初二普及组全真模拟赛

数你太美【第一周】

题目描述

PB 获得了两个正整数数列 ${a_i}$ , ${b_i}$ ,长度分别为 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;$
对于 100% 的数据, $1<=n,m<=9,1<=a_i,b_i<=9。$

分析

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#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;
}

逃亡【第一周】

题目描述

输入格式

第一行三个整数 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)$,那么在不考虑其他点的情况下,它的最优逃跑路线就是它分别到四个边界的距离的最小值即$Min(x, y, n - x, n - y)$。并且此题也不需要考虑其他点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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 +1$(自己头上的数字唯一)或者$a_i$(自己头上的数字不唯一,已经出现过),当两个$a_i$相差2及以上是,是无论如何也无法匀平的。
继续按思路往下走,当最大值和最小值不同时,就只有两种情况,相差一或相等。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#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;
}

The End
「Ô mon âme, n'aspire pas à la vie immortelle, mais épuise le champ du possible.」