整理的算法模板合集: ACM模板
实际上是一个全新的精炼模板整合计划
VP了一下,体验不是太好,区分度不是很好,简单题太简单,难题看着就不想写…没什么意思
比赛地址:
https://ac.nowcoder.com/acm/contest/15600
%VP地址(密码 swpuacm):
%[https://ac.nowcoder.com/acm/contest/16646#description]https://ac.nowcoder.com/acm/contest/16646#description)
目录
第十一届山东省大学生程序设计竞赛(9 / 13)
B. Build Roads
Problem
给定一个 n n n 个点的无向完全图, i i i 和 j j j 之前的边权是 gcd ( a i , a j ) \gcd(a_i,a_j) gcd(ai,aj) ,保证数组 a 随机,求 MST。
Solution
边权为 gcd ( a i , a j ) \gcd(a_i, a_j) gcd(ai,aj),显然如果存在一个点 a x a_x ax 是素数,则从该点向所有的点连边,这样连接的 n − 1 n-1 n−1条边的权值都是1,答案就是 n − 1 n-1 n−1 。
若 L = R L=R L=R,则 R + L + 1 = 1 R+L+1=1 R+L+1=1,模1之后得到的显然都是0,也就是说 n 2 n^2 n2 条边的权值都是 L L L,答案显然就是 L × ( n − 1 ) L\times (n-1) L×(n−1)。
然后因为 n n n 比较大, n ≤ 1 0 5 n\le 10^5 n≤105,所以我们考虑分情况讨论。
若 n n n 比较小,可以直接暴力 O ( n 2 ) O(n^2) O(n2) 连边然后求最小生成树即可。
若 n n n 较大,若 R − L + 1 R-L+1 R−L+1 较大,则根据素数分布,int范围内的素数间距大概就是几百左右,这样 L ∼ L + ( R − L + 1 ) L\sim L+(R-L+1) L∼L+(R−L+1) 中一定会有素数,也就是说一定会出现一个 a i is prime a_i\ \text{is\ prime} ai is prime,答案显然就是上面讨论的 n − 1 n-1 n−1。
若 n n n 较大, R − L + 1 R-L+1 R−L+1 较小,出题人可以找一个没有素数的区间 [ L , R ] [L,R] [L,R],那么答案还是 n − 1 n-1 n−1 吗?显然仍然是,因为 n n n 较大, R − L + 1 R-L+1 R−L+1 较小说明 a 1 ∼ a n a_1\sim a_n a1∼an 一定会把 [ L , R ] [L,R] [L,R] 给取满了,也就是 a i a_i ai 是一堆连续的数,而相邻两个数互质,所以答案一定还是 n − 1 n-1 n−1。
Code
#include <bits/stdc++.h>
using namespace std;
using ull = unsigned long long;
const int maxn = 2e5+5;
bool prime[maxn];
int n,L,R,a[maxn];
ull seed;
void getprime()
{
memset(prime,1,sizeof(prime));
prime[1] = 1;
for(int i = 2;i <= 200000;++i){
if(prime[i]){
for(int j = i+i;j <= 200000;j += i)prime[j] = 0;
}
}
}
ull xorshift64()
{
ull x = seed;
x ^= x<<13;
x ^= x>>7;
x ^= x<<17;
return seed=x;
}
int gen()
{
return xorshift64()%(R-L+1