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;
}