AtCoder Beginner Contest 142 题解

AtCoder Beginner Contest 142 题解

A.Odds of Oddness

◇题目传送门◆

题目大意

给定一个数 N N N,求从 1 1 1 N N N中的数中抽出一个奇数的概率是多少。

分析

水题。

参考程序

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

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	int N;
	scanf("%d" ,&N);
	int tmp = 0;
	for(int i = 1; i <= N; i++)
		if(i % 2) tmp++;
	printf("%f", 1.0 * tmp / N);
	return 0;
}

B.Roller Coaster

◇题目传送门◆

题目大意

找出比一个序列中比 K K K大的的数的个数

分析

水题,扫一遍就够了。

参考程序

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

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	int N, t, cnt = 0;
	scanf("%d %d", &N, &t);
	for(int i = 1; i <= N; i++) {
		int x;
		scanf("%d", &x);
		if(x >= t) cnt++;
	}
	printf("%d\n", cnt);
	return 0;
}

C.Go to School

◇题目传送门◆

题目大意

给定一个学校里学生来的时间点,求将每个学生按时间顺序排序后输出编号。

分析

将每个数的编号记下来后排序输出即可。

参考程序

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

const int Maxn = 1e5;

struct Node {
	int val, id;
	bool operator < (const Node &rhs) const {return val < rhs.val;}
};

int N;
Node A[Maxn + 5];

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	scanf("%d", &N);
	for(int i = 1; i <= N; i++)
		scanf("%d", &A[i].val), A[i].id = i;
	sort(A + 1, A + N + 1);
	for(int i = 1; i <= N; i++)
		printf("%d ", A[i].id);
	return 0;
}

D.Disjoint Set of Common Divisors

◇题目传送门◆

题目大意

给定两个数 A , B A,B A,B,要求选出 gcd ⁡ ( A , B ) \gcd(A,B) gcd(A,B)中的任意的因数,使得这些因数互素。求最多可以选多少个因数。

分析

简单分析一下就可以发现,我们要选的数就是 gcd ⁡ ( A , B ) \gcd(A,B) gcd(A,B)中的不同的质因数个数+1即可(1也可以算在里面)。

参考程序

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

typedef long long ll;
const int Maxn = 1e6;

ll GCD(ll x, ll y) {
	if(y == 0) return x;
	return GCD(y, x % y);
}

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	ll x, y;
	scanf("%lld %lld", &x, &y);
	int cnt = 1;
	ll g = GCD(x, y);
	for(ll i = 2; i * i <= g; i++) {
		if(g % i == 0)cnt++;
		while(g % i == 0) g /= i;
	}
	if(g > 1) cnt++;
	printf("%d\n", cnt);
	return 0;
}

E.Get Everything

◇题目传送门◆

题目大意

M M M把钥匙和 N N N个箱子,使用第 i i i把钥匙需要 A i A_i Ai的代价,但能打开 B i B_i Bi个箱子(箱子的编号给定),求出打开所有的箱子需要的代价。

分析

考虑到 N N N极其小,所以我们可以考虑状压。

定义状态 f ( i , S ) f(i,S) f(i,S)为用前 i i i把钥匙,打开在集合 S S S中的箱子所用的最小代价。

转移显然,看程序就是了。

参考程序

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

const int Maxn = 12;
const int Maxm = 1000;
const int INF = 0x3f3f3f3f;

int N, M;
struct Node {
	int A, C;
};
Node A[100000 + 5];

int f[Maxm + 5][(1 << Maxn) + 5];

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	scanf("%d %d" ,&N, &M);
	for(int i = 1; i <= M; i++) {
		int x;
		scanf("%d %d", &A[i].A, &x);
		int t = 0;
		for(int j = 1; j <= x; j++) {
			int tmp;
			scanf("%d", &tmp);
			t |= (1 << (tmp - 1));
		}
		A[i].C = t;
	}
	memset(f, 0x3f, sizeof f);
	f[0][0] = 0;
	for(int i = 1; i <= M; i++) {
		for(int s = 0; s < (1 << N); s++) {
			int s1 = s | A[i].C;
			f[i][s1] = min(f[i][s1], f[i - 1][s] + A[i].A);
			f[i][s] = min(f[i][s], f[i - 1][s]);
		}
	}
	if(f[M][(1 << N) - 1] != INF)printf("%d\n", f[M][(1 << N) - 1]);
	else puts("-1");
	return 0;
}

F.Pure

◇题目传送门◆

题目大意

给定一个有向图图,要求从里面选出一个子图,使得这个子图中所有的点的出度和入度都是1。

分析

分析一下会发现当图中不存在环时是无解的。

那么问题就变成了在图上找到一个环。

具体还是见代码吧。。。

参考程序

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

const int Maxn = 1000;
const int Maxm = 2000;

vector<int> G[Maxn + 5];

int N, M;
bool vis[Maxn + 5];
int dep[Maxn + 5], ed;
vector<int> ans;

bool DFS(int u) {
	vector<int> tmp;
	int t = -1;
	for(int i = 0; i < (int)G[u].size(); i++) {
		int v = G[u][i];
		if(dep[v] != -1) {
			if(t == -1) t = v;
			else if(dep[v] > dep[t]) t = v;
		}
		if(!vis[v]) tmp.push_back(v);
		vis[v] = true;
	}
	if(t == -1) {
		for(int i = 0; i < (int)tmp.size(); i++) {
			int v = tmp[i];
			dep[v] = dep[u] + 1;
			if(DFS(v)) {
				if(dep[u] >= dep[ed])
					ans.push_back(u);
				return true;
			}
			dep[v] = -1;
		}
		for(int i = 0; i < (int)tmp.size(); i++)
			vis[tmp[i]] = false;
		return false;
	} else {
		ed = t;
		ans.push_back(u);
		return true;
	}
}

int main() {
#ifdef LOACL
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	scanf("%d %d", &N, &M);
	for(int i = 1; i <= M; i++) {
		int u, v;
		scanf("%d %d", &u, &v);
		G[u].push_back(v);
	}
	memset(dep, -1, sizeof dep);
	for(int i = 1; i <= N; i++) {
		memset(vis, false, sizeof vis);
		vis[i] = true, dep[i] = 0;
		if(DFS(i)) {
			printf("%d\n", ans.size());
			for(int i = (int)ans.size() - 1; i >= 0; i--)
				printf("%d\n", ans[i]);
			return 0;
		}
		dep[i] = -1;
	}
	puts("-1");
	return 0;
}
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道题的简要题解: A - Dodecagon 题目描述:已知一个正十二边形的边长,求它的面积。 解题思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 题目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解题思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 题目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解题思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 题目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解题思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值