Codeforces Round #748 (Div. 3) (D1 - E)

D1. All are Same

同余题 求所有数加上k*x之后的值相等时k的最大值 即所有数同余k相等 我们可以找到最小值 所有数减去这个最小值然后求gcd所得值即为k的最大值
为什么是减去最小值呢? 有 a ≡ b(mod k) 等价于 (a - b) % k = 0 所有我们必须使序列所有数减去一个序列之中的数字来求gcd 减去最小值是为了使得处理后的序列中不包含负数
代码

#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (n); i ++ )

using namespace std;

typedef pair<int, int> PII;

const int N = 100, INF = 1e8;

inline int read()
{
	register int x = 0, k = 1;
	char c = getchar();
	while (c < '0' || c > '9')
	{
		if (c == '-') k = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9')
	{
		x = (x << 3) + (x << 1) + (c ^ 48);
		c = getchar();
	}
	return x * k;
}

int gcd(int a, int b)
{
	return b ? gcd(b, a % b) : a;
}

void solve()
{
	int n; n = read();
	vector<int> a(n);
	rep(i, n) a[i] = read();
	
	vector<int> dif;
	int tmp = *min_element(a.begin(), a.end());
	rep(i, n) if (a[i] != tmp) dif.push_back(a[i] - tmp);

	if (dif.size() == 0) {puts("-1"); return;}

	int ans = dif[0];
	rep(i, dif.size()) ans = gcd(ans, dif[i]);
	printf("%d\n", ans);
}

int main()
{
	int t;
	t = read();

	while (t -- )
	{
		solve();
	}

	return 0;
}

D2 - Half of Same

D2和D1相似 是要去找k使得一半以上的序列元素减去 k * x 可以相等 我们可以想到 在这个序列中随便取两个数 这两个数均是在减去最大k * x后的相等序列的可能性为四分之一 我们可以用1e3次寻找 寻找后验证是否满足题意 这一千次寻找均不满足题意的可能性为四分之三的一千次方 能看出很小了 担心会wa的话可以再搞大一点
验证是每次找到的两数之差的因数都有可能是k 所以再遍历一次k就好 如果当前k满足题意 则记录 每次求最大值
代码

#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (n); i ++ )

using namespace std;

typedef long long ll;

const int N = 110, INF = 1e6;

inline int read()
{
	register int x = 0, k = 1;
	char c = getchar();
	while (c < '0' || c > '9')
	{
		if (c == '-') k = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9')
	{
		x = (x << 3) + (x << 1) + (c ^ 48);
		c = getchar();
	}
	return x * k;
}

int gcd(int a, int b)
{
	return b ? gcd(b, a % b) : a;
}

int n;
int a[N];

bool check(int k)
{
	map<int, int> mp;
	for (int i = 1; i <= n; i ++ )
	{
		mp[(a[i] + (ll)k * INF) % k] ++ ;
		if (mp[(a[i] + (ll)k * INF) % k] * 2 >= n) return true; 
	}
	return false;
}

void solve()
{
	n = read();
	for (int i = 1; i <= n; i ++ ) a[i] = read();
	sort(a + 1, a + 1 + n);
	int sum = 1, flag = 0;;
	for (int i = 2; i <= n; i ++ ) 
		if (a[i] == a[i - 1])
		{
			sum ++ ;
			if (sum * 2 >= n) flag = 1;
		}
		else sum = 1;
	if (flag) {puts("-1"); return;}
	srand(time(0));
	int ans = -1;
	int t = 1e3;
	while (t -- )
	{
		int x = rand() % n + 1, y = rand() % n + 1;
		int tmp = abs(a[x] - a[y]);
		for (int i = 1; i * i <= tmp; i ++ )
			if (tmp % i == 0)
			{
				if (check(i)) ans = max(ans, i);
				if (check(tmp / i)) ans = max(ans, tmp / i);
			}
	}
	printf("%d\n", ans);
}

int main()
{
	int t;
	t = read();

	while (t -- )
	{
		solve();
	}

	return 0;
}

E. Gardener and Tree

题目为给一棵无根树 每切割一次会把所有树的最外面一圈给割掉 即把所有叶子结点全给删掉 我们可以将它看成一张拓扑图 用一个优先队列来维护每次入度为1的点 与k相比查看是否删掉
代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> PII;

const int N = 4e5 + 10, M = N * 2;

inline int read()
{
	register int x = 0, k = 1;
	char c = getchar();
	while (c < '0' || c > '9')
	{
		if (c == '-') k = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9')
	{
		x = (x << 3) + (x << 1) + (c ^ 48);
		c = getchar();
	}
	return x * k;
}

int n, k;
int h[N], e[M], ne[M], idx;
int d[N];

void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void solve()
{
	n = read(), k = read();
	memset(h, -1, sizeof h); idx = 0;
	for (int i = 0; i < n - 1; i ++ )
	{
		int a, b; a = read(), b = read();
		add(a, b), add(b, a);
		d[a] ++, d[b] ++ ;
	}

	if (n == 1)
	{
		if (k >= 1) puts("0");
		else puts("1");
		return;
	}

	priority_queue<PII, vector<PII>, greater<PII>> Q;
	for (int i = 1; i <= n; i ++ ) if (d[i] == 1) Q.push(make_pair(1, i));

	int sum = 0;
	while (Q.size())
	{
		auto t = Q.top(); Q.pop();
		int from = t.second, step = t.first;
		if (step > k) continue;
		sum ++ ;
		for (int i = h[from]; ~i; i = ne[i])
		{
			int to = e[i];
			if ( -- d[to] == 1)
				Q.push(make_pair(step + 1, to));
		}
	}

	printf("%d\n", n - sum);
	for (int i = 1; i <= n; i ++ ) d[i] = 0;
}

int main()
{
	int t;
	t = read();

	while (t -- )
	{
		solve();
	}

	return 0;
}
上一篇:初识Servlet --d1


下一篇:C语言代码第二天