Loading

Codeforces Round #677 (Div. 3) A-E

A. Boring Apartments

模拟

#include <iostream>
using namespace std;
int main()
{		
	//freopen("data.txt", "r", stdin);
	int t;
	cin >> t;
	while(t--)
	{

		int x;
		cin >> x;
		int len = 0, num = x % 10;
		while(x)
		{
			len++;
			x /= 10;
		}
		cout << (num - 1) * 10 + (len == 1 ? 1 : (1 + len) * len / 2) << endl;
	}
	return 0;
}

B.Yet Another Bookshelf

大意是给一个01序列,每次可以选择其中l到r的一段往左或者右平移一格(前提是那个位置为0),问最少多少次能让所有的1均相邻。

显然答案是第一个1到最后一个1之间的0的个数。

#include <iostream>
using namespace std;
int n, a[55];
int main()
{
	//freopen("data.txt", "r", stdin);
	int t;
	cin >> t;
	while(t--)
	{
		cin >> n;
		for(int i = 1; i <= n; i++) cin >> a[i];
		int ans = 0;
		int last = 0;
		for(int i = 1; i <= n; i++)
		{
			if(last)
			{
				if(a[i])
				{
					ans += i - last - 1;
					last = i;
				}
			}
			else 
			{
				if(a[i]) last = i;
			}
		}
		cout << ans << endl;
	}
	return 0;
}

C.Dominant Piranha

大意是有n条鱼,每条鱼有一个size,一条鱼可以吃掉相邻的且size小于它的鱼同时自己的size会加一,最后剩下的是鱼王,输出鱼王的编号(没有的话输出-1)。

容易知道序列仅有一种数时无解,否则一定有解。因为是随意输出,因此可以扫一遍序列找到最大的size,然后从所有size为最大size的鱼里面挑一条能吃掉相邻鱼的即可,因为只要它一开始能吃掉相邻的鱼,它的size就严格大于其他任意鱼了。

#include <iostream>
using namespace std;
int n, a[300005];
int main()
{
	//freopen("data.txt", "r", stdin);
	int t;
	cin >> t;
	while(t--)
	{
		cin >> n;
		a[0] = 0x3f3f3f3f, a[n + 1] = 0x3f3f3f3f;
		for(int i =1; i <= n; i++) cin >> a[i];
		int mmax = 0;
		for(int i = 1; i <= n; i++)
		{
			mmax = max(mmax, a[i]);
		}
		int cnt = 0, pos = 0;
		for(int i = 1; i <= n; i++)
		{
			if(a[i] == mmax) 
			{
				cnt++;
				if(a[i] > a[i - 1] || a[i] > a[i + 1]) pos = i;
			}

		}
		if(cnt == n) cout << -1 << endl;
		else cout << pos << endl;
	}
	return 0;
}

D.Districts Connection

大意是给n个点,每个点有一个值,求一个连接n个点的树,并且连边的两个点之间的值不同。

由于点只有5e3个,直接\(O(n^2)\)扫一遍,把值不同的两个点之间建边扔进vector,然后执行类似kruskal的过程即可(并查集的fa数组记得每次初始化)。

#include <iostream>
#include <vector>
using namespace std;
int n, a[5005];
int fa[5005];
int get(int x)
{
	if(x == fa[x]) return x;
	return fa[x] = get(fa[x]);
}
struct edge
{
	int x, y;
};
int main()
{
	//freopen("data.txt","r", stdin);
	int t;
	cin >> t;
	while(t--)
	{
		cin >> n;
		vector<edge> v;
		for(int i = 1; i <= n; i++) 
		{
			cin >> a[i];
			fa[i] = i;
		}
		for(int i = 1; i <= n; i++)
		{
			for(int j = i + 1; j <= n; j++)
			{
				if(a[i] != a[j]) v.push_back(edge{i, j});
			}
		}
		int cnt = 0;
		vector<edge> ans;
		for(int i = 0; i < v.size(); i++)
		{
			if(cnt == n - 1)break;
			int xx = get(v[i].x), yy = get(v[i].y);
			if(xx == yy) continue;
			fa[xx] = yy;
			cnt++;
			ans.push_back(v[i]);
		}
		if(cnt == n - 1)
		{
			cout << "YES" << endl;
			for(int i = 0; i < ans.size(); i++)
			{
				cout << ans[i].x << ' ' << ans[i].y << endl;
			}
		}
		else cout << "NO" << endl;
	}
	return 0;
}

E.Two Round Dances

把1到n这n个数分成两组,问有多少种分法,其中1 4 2 3和4 2 3 1这样的算一种。

排列组合题,首先挑出来一组,是\(C^{\frac{2}{n}}_n\),这样的话其实两个组的数都能确定下来了,然后是顺序问题,对于每一组,首先是求全排列,但这样还无法排除掉循环的情况(如1 4 2 3和4 2 3 1),因此要除以每组的长度\(\frac{2}{n}\),最后别忘除以2(因为第一组1 4 2 3 第二组5 6 8 7和第二组1 4 2 3 第一组5 6 8 7在题目里算一种)

#include <iostream>
using namespace std;
long long C(int n, int m)
{
	if (m < n - m) m = n - m;
	long long ans = 1;
	for (int i = m + 1; i <= n; i++) ans *= i;
	for (int i = 1; i <= n - m; i++) ans /= i;
	return ans;
}
long long f(int n)
{
	long long ans = 1;
	for(int i = 1; i <= n; i++) ans = ans * (1ll * i);
	return ans;
}
int main()
{
	//freopen("data.txt", "r", stdin);
	int n;
	cin >> n; 
	cout << C(n, n / 2) * f(n / 2) * f(n / 2) / (n / 2) / (n / 2) / 2;
	return 0;
}
posted @ 2020-10-21 20:05  脂环  阅读(189)  评论(0编辑  收藏  举报