AtCoder Beginner Contest 210 A~E题解
A - Cabbages
-
题意
有 n n n个物品,初始价格为 x x x,当购买量大于等于 a a a时,那么剩下未购买的物品价格按 y y y处理。求最小价格。 -
解题思路
简单贪心,题目中保证了 x > y x >y x>y。需要注意判断 n n n和 a a a的大小关系。 -
AC代码
/**
*@filename:A
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-25 15:41
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
int n,a,x,y;
void solve(){
}
int main(){
cin >> n >> a >> x >> y;
if(n <= a){
cout << n * x << endl;
}
else{
cout << a * x + (n - a) * y;
}
solve();
return 0;
}
B - Bouzu Mekuri
-
题意
给你一个 01 01 01字符串,两个人一次取字符串的开头字符,谁先取到 1 1 1字符谁就输。输出输家的名称。 -
解题思路
水题,遍历即可。 -
AC代码
/**
*@filename:B
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-25 15:44
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
int n;
string s;
int ans;
void solve(){
}
int main(){
cin >> n >> s;
for(int i = 0; i < s.size(); ++ i){
if(s[i] == '1'){
if(!(i & 1)){
cout << "Takahashi" << endl;
}
else{
cout << "Aoki" << endl;
}
break;
}
}
solve();
return 0;
}
C - Colorful Candies
-
题意
给你一个序列,问其中长度为 k k k的连续子序列的最大不重复元素数量是多少。 -
解题思路
很容易想到双指针滑动检索。注意使用 m a p map map更新元素。 -
AC代码
/**
*@filename:C
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-25 15:54
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 5;
const int P = 1e9+7;
int n,k,c[N];
unordered_map<int,int> p;//判断是否符合。
void solve(){
int maxx = 1;
for(int i = 1; i <= k; ++ i){
p[c[i]]++;//先将前i个放入map中
}
maxx = max(maxx,(int)p.size());
for(int i = k + 1; i <= n; ++ i){
p[c[i]] ++;
p[c[i - k]]--;
if(p[c[i - k]] == 0)p.erase(c[i - k]);
maxx = max(maxx,(int)p.size());
}
cout << maxx << endl;
}
int main(){
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; ++ i){
scanf("%d", &c[i]);
}
solve();
return 0;
}
D - National Railway
-
题意
给你一个 n × m n\times m n×m大小的地点,问你需要选择两个地点建地点站,并在其之间建立轨道,问最小花费。 -
解题思路
根据题意,实际上建立轨道的花费相当于是它们的曼哈顿距离 × c \times c ×c,所以如果我们建好了一个站,那么相当于我可以行走到下一个地点再建一个站,所以我们可以先记录好前半部分的最小花费。我们可以用 d p [ i ] [ j ] dp[i][j] dp[i][j]来表示已经建好了一个地铁站,且已经走到了 ( i , j ) (i,j) (i,j),为了考虑全面,我们遍历的方向实际上就是东北和东南方向。所以我们要分两次来跑,对于东南方向,状态转移方程易知: d p [ i ] [ j ] = { a i j , d p [ i − 1 ] [ j ] + c , d p [ i ] [ j − 1 ] + c } dp[i][j] = \{a_{ij},dp[i-1][j]+c,dp[i][j-1]+c\} dp[i][j]={aij,dp[i−1][j]+c,dp[i][j−1]+c}。那么我们处理好 d p dp dp数组之后,还有一点就是如何确定最后一个地铁站建在哪最优,哪很明显,我们直接遍历 d p dp dp数组再枚举我们建立的地铁站即可。 -
AC代码
/**
*@filename:D
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-25 16:39
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000 + 5;
const int P = 1e9+7;
const ll INF = 0x3f3f3f3f3f3f3f;
int n,m,c;
ll a[N][N],dp[N][N],ans[N][N];//其中dp[i][j]表示已经建了一站。且当前处于(i,j)。ans[i][j]则表示最后一站在(i,j)处建的最低成本。
void solve(){
fill(dp[0],dp[0] + N * N,INF);
fill(ans[0],ans[0] + N * N,INF);
//从(1,1)开始往右下走。
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= m; ++ j){
dp[i][j] = min(a[i][j],min(dp[i - 1][j],dp[i][j - 1]) + c);//设状态转移方程。
}
}
ll minn = INF;
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= m; ++ j){
ans[i][j] = min(dp[i - 1][j],dp[i][j - 1]) + c + a[i][j];
minn = min(ans[i][j],minn);
}
}
//从(n,m)开始往左上走。
for(int i = n; i >= 1; -- i){
for(int j = 1; j <= m; ++ j){
dp[i][j] = min(a[i][j],min(dp[i + 1][j],dp[i][j - 1]) + c);
}
}
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= m; ++ j){
ans[i][j] = min(dp[i + 1][j],dp[i][j - 1]) + c + a[i][j];
minn = min(ans[i][j],minn);
}
}
printf("%lld\n",minn);
}
int main(){
scanf("%d%d%d", &n, &m, &c);
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= m; ++ j){
scanf("%lld", &a[i][j]);
}
}
solve();
return 0;
}
E - Ring MST
-
题意
最开始有 n n n个点, 0 0 0条边的图。现在给你 m m m种操作,第 i i i操作可以选择 x , 0 ≤ x < n x,0\leq x <n x,0≤x<n,然后将 x x x与 ( x + a i ) m o d n (x+a_i)\mod n (x+ai)modn这两个顶点之间连边,花费为 c i c_i ci,问你使这 n n n个点的最小花费是多少。 -
解题思路
首先要注意一点,相当于是建立最小生成树,而根据Kruskal算法,我们会优先选择权值小的边进行组合,所以我们自然是根据 c i c_i ci来排序。其次,根据这个取余特性,实际上我们是可以重复这个动作获得 g c d ( a i , n ) gcd(a_i,n) gcd(ai,n)个集合,这里我们不做证明。那么当 g c d ( a i , n ) gcd(a_i,n) gcd(ai,n)为 1 1 1时则连通。所以我们不断缩小集合即可。 -
AC代码
/**
*@filename:E
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-25 17:13
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
struct node{
int a,c;
bool operator < (const node &A){
if(c == A.c){
return a < A.a;
}
return c < A.c;
}
};
node nodes[N];
int n,m;
void solve(){
ll ans = 0;
sort(nodes + 1,nodes + 1 + m);
for(int i = 1; i <= m; ++ i){
int temp = __gcd(nodes[i].a,n);
ans += 1LL * (n - temp) * nodes[i].c;
n = temp;
if(n == 1)break;
}
printf("%lld\n",n > 1 ? -1 : ans);
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++ i){
scanf("%d%d", &nodes[i].a, &nodes[i].c);
}
solve();
return 0;
}

浙公网安备 33010602011771号