您的位置:首页 > 其它

模拟赛记录(3):11.02 论想题思路

2015-11-03 07:42 225 查看
第 1 题 我们爱几何 (geometry)

【题目描述】

AngryBacon 和 ftiasch 是好朋友。ftiasch 酷爱几何,于是 AngryBacon 经常会为 ftiasch 出一些几何

题。这次,他又出了一道题目:

给出平面上的 N 个整点,AngryBacon 想选取这 N 个点中的 K 个点,连成一个正 K 边形。

正 K 边形的定义为边数为 K 的多边形,要求 K ≥ 3,各边相等,各角也相等。

AngryBacon 想知道他最多能取多少个点。

【输入格式】

第一行,1 个整数 T, 表示数据组数。接下来是 T 组数据。

每组数据的第一行包含一个整数 N,表示给定的点数。

接下来的 N 行每行两个整数,分别表示一个点的 x, y 坐标。

【输出格式】

对于每组数据,输出一行,包含一个整数,表示算最多可取的点数。如果无法连成任何的合法正多边

形,则输出 −1。

【样例输入】

2

5

1 0

0 1

1 2

2 1

1 1

4

0 1

1 2

2 1

1 1

【样例输出】

4

-1

【数据范围】

• 对于 30% 的数据,1 ≤ N ≤ 50。

• 对于另外 30% 的数据,1 ≤ N ≤ 200。

• 对于 100% 的数据,1 ≤ N ≤ 1, 000,−109 ≤ x, y ≤ 109,1 ≤ T ≤ 20。

• 保证数据中没有重点。

【时间限制】

1.5 秒

第 2 题 我们爱数数 (counting)

【题目描述】TankEngineer 是数数高手,每天早上的乐趣是倒背圆周率。

TankEngineer 的家里有一张圆桌,每个位置按顺时针从 1 到 N 编号,差的绝对值为 1 的两个位置

相邻。特别的,编号为 N 的位置与编号为 1 的位置相邻。

他的家里某天来了 N 个人,编号从 1 到 N。如果编号为 i 的人坐到了编号为 i 的位置或坐到了与编

号为 i 的位置相邻的位置,这个人就会感到开心,反之这个人会感到沮丧。

于是 TankEngineer 想知道,有多少种安排坐位的方法,使所有人都入座,并且使得至少 K 个人开

心。

【输入格式】

第一行,包含两个整数 N, K。

【输出格式】

第一行,包含一个整数,表示合法方案的数量。因为数值太大,你只需要输出结果除以 (109 + 7) 的

余数。

【样例输入】

4 4

【样例输出】

9

【样例解释】

合法的方案有 {1, 2, 3, 4}, {1, 2, 4, 3}, {1, 3, 2, 4}, {2, 1, 3, 4}, {2, 1, 4, 3}, {2, 3, 4, 1}, {4, 1, 2, 3}, {4, 2, 3, 1},

{4, 3, 2, 1} 这九种。

【数据范围】

• 对于 20% 的数据,3 ≤ K ≤ N ≤ 10。

• 对于另外 40% 的数据,3 ≤ K ≤ N ≤ 20。

• 对于 100% 的数据,3 ≤ K ≤ N ≤ 1, 000。

【时间限制】

3 秒

第 3 题 我们爱序列 (sequence)

【题目描述】AngryBacon 非常喜欢序列,与序列有关的一切都喜欢。

AngryBacon 面前摆着一个长度为 N 的序列,每个元素为不超过 M 的正整数。

AngryBacon 会使用 Q 次魔法,每次魔法的内容为一对不超过 M 的正整数 a, b,表示将序列中所有

为 a 的数改写为 b。

AngryBacon 想知道在最后他心爱的序列变成了什么样。

【输入格式】

第一行,包含三个整数 N, M, Q,意义如上所述。

第二行,包含 N 个整数 A1, A2, … , AN,表示初始序列。

接下来的 Q 行,每行两个整数 a, b,意义如上所述。

【输出格式】

输出一行,包含 N 个整数,表示最后序列的形态。

【样例输入】

5 5 3

1 2 3 4 5

3 1

4 3

1 5

5 2 5 3 5

【数据范围】

• 对于 20% 的数据,1 ≤ N, M, Q ≤ 1, 000。

• 对于另外 40% 的数据,1 ≤ N, Q ≤ 100, 000,1 ≤ M ≤ 20。

• 对于 100% 的数据,1 ≤ N, M, Q ≤ 1000, 000,1 ≤ a, b, Ai ≤ M。

【时间限制】

2 秒

这套题并不是我们自己考的,是一个朋友发给我的,T2仍然处于不会的状态=.=

T1表示自己想问题太狭隘被虐。本来一看像是计算几何,就没有继续看下去的动力了。想到自己会的判断正K边形的方法貌似只有暴力计算边长,邻边夹角,判断是否相同。并没有去想一个很简单的问题,顶点坐标都是整数,如果存在一个正K边形,那么K==4。稍微想想也能明白,K != 4时,邻边夹角必然不是90°,这个时候要满足所有顶点坐标都为整数是不可能的。然而自己并没有往这方面去想,只是去想:这道题是不是需要什么高端数学知识来快速判断是否正K边形?【思路问题,好比自己是在DFS,在错误的道路上越走越远,而若BFS,稍微想到“是否存在K比较大的情况”,便可以想到这个结论】

T2暂时不会,没去认真看。

T3便简单一点,自己还写了一下。大概是乱搞?因为我也说不清这到底属于邻接表还是链表还是并查集。是基于想到的一个处理方法来实现的:设m个集合,集合i中的每个元素j表示,在初始序列中为j的元素在若干次操作后为i。对于每次操作(a,b),对应着把集合a中所有元素拿到集合b中。

需要注意的是输出100w个整数并不快,大概要2.5s. 所以这道题必须输出优化,也是在这里我接触到了和读入优化相似的输出优化=.=

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

int n, m, q, h[1000005], nx[1000005], t[1000005];
int beg[1000005], c[1000005];

void get(int &x)
{
char c = getchar(); x = 0;
while(c < '0' || c > '9') c = getchar();
while(c <= '9' && c >= '0') x = x*10+c-48, c = getchar();
}

void put(int x)
{
int num = 0; char c[15];
while(x) c[++num] = (x%10)+48, x /= 10;
while(num) putchar(c[num--]);
putchar('\n');
}

int main()
{
scanf("%d %d %d", &n, &m, &q);
for(int i = 1; i <= n; i++) scanf("%d", beg+i);
for(int i = 1; i <= m; i++) h[i] = t[i] = i;

while(q--)
{
int a, b; get(a); get(b);
if(!h[a] || a == b) continue;

if(h[b]) nx[t[b]] = h[a]; else h[b] = h[a];
t[b] = t[a], h[a] = t[a] = 0;
}

for(int i = 1; i <= m; i++)
for(int j = h[i]; j; j = nx[j]) c[j] = i;

for(int i = 1; i <= n; i++) put(c[beg[i]]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: