ACL Contest 1(补题)
Posted 佐鼬Jun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACL Contest 1(补题)相关的知识,希望对你有一定的参考价值。
A - Reachable Towns
题目链接: link.
题意:
在二维坐标轴给定 N N N个点,每个点都可以跳向向 x 和 y x和y x和y值比它大或者 x 和 y x和y x和y值比它小的点,现在让你输出每个点可以跳的最多的点数(自己也可以跳自己).
思路:
可以在每个跳的点对之间连一条边,代表这对点可以相互跳,把所有点都连完边后,每一个连通块内的点,一定是可以相互跳的,所以连通块的大小就是这个连通块每个点可以跳的最多点数。这个可以通过并查集实现,但不能每两个点之间判断一下是否能跳,时间复杂度太高,为 O ( n 2 ) O(n^2) O(n2),可以利用单调栈来降低时间复杂度,先按照 x x x的值升序排序,然后单调栈内维护的是,并查集内 y y y值的最小值,即单调栈内的值是单调递减的。每次取出来的点,取出来值如果在栈顶点的右上方,就把它与栈顶点结合成一个集合,并把栈顶弹出,然后再次判断。最后知道栈空,或者该点在栈顶点的右下角,即无法相互跳,那么此时就把这个点放进栈中。最后输出每个点所在并查集的大小,就是每个点可以跳的最多点数。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
const int inf = 0x3f3f3f3f;
typedef pair<int, int> PII;
struct node
int x, y, id;
a[N];
int n;
int Size[N], fa[N];
PII sta[N];
int tt;
bool cmp(node a, node b) return a.x < b.x;
int find(int x)
if (x != fa[x]) fa[x] = find(fa[x]);
return fa[x];
int main()
cin >> n;
for (int i = 0, x, y; i < n; i++)
cin >> x >> y;
a[i] = x, y, i;
for (int i = 0; i < n; i++)
fa[i] = i, Size[i] = 1;
sort(a, a + n, cmp);
for (int i = 0; i < n; i++)
if (tt == 0)
sta[++tt] = a[i].id, a[i].y;
else
int minv = a[i].y;
while (tt && a[i].y > sta[tt].second)
minv = min(minv, sta[tt].second);
int x = find(a[i].id), y = find(sta[tt].first);
if (x != y)
fa[x] = y;
Size[y] += Size[x];
tt--;
sta[++tt] = a[i].id, minv;
for (int i = 0; i < n; i++)
cout << Size[find(i)] << endl;
B - Sum is Multiple
题目链接: link.
题意:
给定一个数字
N
N
N,现在让你找到一个最小的
k
k
k,让
1
+
2
+
.
.
.
.
+
k
1+2+....+k
1+2+....+k是
N
N
N的倍数,也就是说这个和能整除
N
N
N
思路:
把原式处理一下,就是
k
(
k
+
1
)
2
=
α
N
\\frack(k+1)2=αN
2k(k+1)=αN,即
k
(
k
+
1
)
=
2
α
N
k(k+1)=2αN
k(k+1)=2αN,也就是说
2
×
N
∣
k
×
(
k
+
1
)
2×N|k×(k+1)
2×N∣k×(k+1)
下面的
n
n
n就代替
2
×
N
2×N
2×N现在令
s
=
k
×
(
k
+
1
)
s=k×(k+1)
s=k×(k+1),使
n
n
n和
s
s
s质因数分解,就变成了
n
=
∏
p
i
k
i
n=\\prod p_i^k_i
n=∏piki
s
=
∏
p
j
k
j
s=\\prod p_j^k_j
s=∏pjkj。
对于
∀
i
∀i
∀i ,
p
i
k
i
∣
s
p_i^k_i|s
piki∣s,又可以观察到
k
和
k
+
1
k和k+1
k和k+1互质,所以对于一部分
i
i
i,
p
i
k
i
∣
k
p_i^k_i|k
piki∣k,
p
i
k
i
∣
(
k
+
1
)
p_i^k_i|(k+1)
piki∣(k+1)
所以可以枚举 n n n的因数 a 和 b a和b a和b,即 a × b = n a×b=n a×b=n且 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1, k = a x k=ax k=ax, k + 1 = b y k+1=by k+1=by,所以 b y − a x = 1 by-ax=1 by−ax=1,而这个式子可以由 e x g c d exgcd exgcd扩展欧几里得算出来,用扩展欧几里得算 b y + a x ′ = 1 by+ax'=1 by+ax′=1,这个式子的解,算出 x 和 y x和y x和y,看 x 和 y x和y x和y那个是负数那个就是我们要找的 a a a,因为用下面代码 e x g c d exgcd exgcd算出来的系数只是 ∣ x ∣ + ∣ y ∣ |x|+|y| ∣x∣+∣y∣最小,当然也可以令 y = y , x = x ′ y=y,x=x' y=y,x=x′,用扩欧算出来的是后,如果算出来的 x ′ x' x′是 > = 0 >=0 >=0,再调整一下系数把 x ′ x' x′变为负数即可。
#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
#define ll long long
ll exgcd(ll a, ll b, ll &x, ll &y)
if (!b)
x = 1, y = 0;
return a;
ll d = exgcd(b, a % b, y, x);
y = y - a / b * x;
return d;
int main()
ll n;
cin >> n;
if (n == 1)
puts("1");
return 0;
n *= 2;
ll res = 1e18;
for (ll i = 2; i <= n / i; i++)
ll a, b;
if (n % i == 0)
a = i, b = n / i;
if (__gcd(a, b) != 1) continue;
ll x, y;
exgcd(a, b, x, y);
if (x < 0)
res 以上是关于ACL Contest 1(补题)的主要内容,如果未能解决你的问题,请参考以下文章
补题日记[2022牛客暑期多校4]A-Task Computing
补题日记[2022牛客暑期多校4]A-Task Computing
SDUT 2021 Spring Individual Contest(for 20) - 1补题
AtCoder Beginner Contest 222(补题)