AtCoder Beginner Contest 198题解

题目链接

C题比较坑一点。

A题

题意:给你n个糖\(n >= 1\),每个人至少拿一个,问你分给两个人有几种分发。

思路:\(n-1\)种。
代码如下

int main()
{
	IOS;
	int n;
	cin >> n;
	cout << n - 1 << endl;		
	return 0;
}

B题

题意:给你一个整数n,问你是否能通过添加前导0使得它是一个回文数。

思路:直接去掉后缀0,然后判断是否是回文即可,因为后缀0一定可以通过添加前导0抵消,输入的又是整数,不包含前导0的情况。
代码如下

int main()
{
	IOS;
	string s;
	cin >> s;
	int r = s.size() - 1;
	while(s[r] == '0')	r --;
	bool flag = true;
	for(int i = 0 ; i < (r + 1) / 2 ; i ++)
		if(s[i] != s[r - i])
		{
			flag = false;
			break;
		}
	if(flag) cout << "Yes" << endl;
	else cout << "No" << endl;
	return 0;
}

C题

题意:你初始在\((0, 0)\)点,你每次能移动\(R\)的距离,问你最少移动多少次能到达目标点\((x, y)\)

思路:直接计算出起点到目标点的直线距离dist,然后计算移动次数,注意当\(R > dist\)的时候,要多移动一次。
代码如下

int main()
{
	IOS;
	double r, x, y;
	cin >> r >> x >> y;
	double dis = sqrt(x * x + y * y);
	ll res = dis / r;
	if(res * r < dis) res ++;
	if(r > dis) res ++;
	cout << res << endl;
	return 0;
}

D题

题意:给你三个字符串A、B、C,问你有没有办法通过将字母替换为\(0 ~ 9\)的数字,满足字母和数字唯一对应,使得替换后满足\(A + B = C\)

思路:注意每个字符串首字母不能为0,然后暴搜即可。
代码如下

set <char> mp;
vector<char> v;
bool st[10];
int ans[10];
string s1, s2, s3;
ll a, b, c;
bool bj[10];
 
bool dfs(int u)
{
	if(u == v.size())
	{
		a = b = c = 0;
		for(int i = 0 ; i < s1.size() ; i ++)
		{
			for(int j = 0 ; j < v.size() ; j ++)
				if(s1[i] == v[j])
					a = a * 10 + ans[j];
		}
		for(int i = 0 ; i < s2.size() ; i ++)
		{
			for(int j = 0 ; j < v.size() ; j ++)
				if(s2[i] == v[j])
					b = b * 10 + ans[j];
		}
		for(int i = 0 ; i < s3.size() ; i ++)
		{
			for(int j = 0 ; j < v.size() ; j ++)
				if(s3[i] == v[j])
					c = c * 10 + ans[j];
		}
		if(a + b == c) return true;
		return false;
	}
	
	for(int i = 0 ; i < 10 ; i ++)
	{
		if(!i && bj[u]) continue;
		if(st[i]) continue;
		ans[u] = i;
		st[i] = true;
		if(dfs(u + 1)) return true;
		st[i] = false;
	}
	return false;
}
 
int main()
{
	IOS;
	cin >> s1 >> s2 >> s3;
	for(int i = 0 ; i < s1.size() ; i ++) mp.insert(s1[i]);
	for(int i = 0 ; i < s2.size() ; i ++) mp.insert(s2[i]);
	for(int i = 0 ; i < s3.size() ; i ++) mp.insert(s3[i]);
	
	for(auto x : mp) v.push_back(x);
	for(int i = 0 ; i < v.size() ; i ++)
		if(v[i] == s1[0] || v[i] == s2[0] || v[i] == s3[0])
			bj[i] = true;	

	if(!dfs(0))
		cout << "UNSOLVABLE" << endl;
	else
	{
		cout << a << endl;
		cout << b << endl;
		cout << c << endl;		
	}	
	return 0;
}

E题

题意:给你一颗树,每个结点有一个颜色,让你找出所有从1到其的最短路径上,那个点的颜色唯一出现的点。

思路:就是树的遍历,维护一下颜色的出现cnt数组即可。
代码如下

int h[N], e[M], ne[M], idx;
int color[N];
int cnt[N];
bool st[N];
int n;
 
void add(int a, int b)
{
	e[idx] = b;
	ne[idx] = h[a];
	h[a] = idx ++;
}
 
void dfs(int u, int fa)
{
	cnt[color[u]] ++;
	if(cnt[color[u]] == 1) st[u] = true;
	
	for(int i = h[u] ; ~i ; i = ne[i])
	{
		int j = e[i];
		if(j == fa) continue;
		dfs(j, u);
	}
	cnt[color[u]] --;
}
 
int main()
{
	IOS;
	cin >> n;
	for(int i = 1 ; i <= n ; i ++) cin >> color[i];
	memset(h, -1, sizeof h);
	for(int i = 1 ; i < n ; i ++)
	{
		int a, b;
		cin >> a >> b;
		add(a, b);
		add(b, a);
	}
	
	dfs(1, -1);
	
	for(int i = 1 ; i <= n ; i ++)
		if(st[i])
			cout << i << endl;
	
	return 0;
}
posted @ 2021-04-11 23:45  beatlesss  阅读(68)  评论(0编辑  收藏  举报