Codeforces Round #540 (Div. 3) A~F1题解
A. Water Buying
-
题意
1 L 1L 1L的饮用水需要 a a a, 2 L 2L 2L的饮用水需要 b b b。你需要购买 n L nL nL水,问需要花费的最小代价。 -
解题思路
判断哪个更优即可,即 2 × a 2\times a 2×a和 b b b的大小。当然我们还需要考虑 n n n的奇偶性。 -
AC代码
/**
*@filename:A
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-27 10:21
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
int t;
ll n,a,b;
void solve(){
if(a * 2 <= b){
cout << n * a << endl;
}
else{
cout << n / 2 * b + ((n % 2) ? a : 0) << endl;
}
}
int main(){
cin >> t;
while(t -- ){
cin >> n >> a >> b;
solve();
}
return 0;
}
B. Tanya and Candies
-
题意
给你 n n n个糖果,移除其中一个糖果,使得剩下的奇数序号的糖果数总和等于偶数序号的糖果数总和。 -
解题思路
枚举每个糖果,利用前缀和处理达到 O ( 1 ) O(1) O(1)计算即可。注意移除了一个糖果后,后面的奇数位变偶数位置,偶数位置变奇数位置,注意细节处理。 -
AC代码
/**
*@filename:B
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-27 10:26
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200000 + 5;
const int P = 1e9+7;
int n,a[N];
ll pre_even[N],pre_odd[N];
void solve(){
int ans = 0;
for(int i = 1; i <= n; ++ i){
if(pre_odd[i - 1] + pre_even[n] - pre_even[i] == pre_even[i - 1] + pre_odd[n] - pre_odd[i]){
ans ++;
}
}
cout << ans << endl;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
scanf("%d", &a[i]);
if(i & 1){
pre_odd[i] = pre_odd[i - 1] + a[i];
pre_even[i] = pre_even[i - 1];
}
else{
pre_odd[i] = pre_odd[i - 1];
pre_even[i] = pre_even[i - 1] + a[i];
}
}
solve();
return 0;
}
C. Palindromic Matrix
-
题意
给你 n 2 n^2 n2个数,需要你将这些数填入 n × n n\times n n×n的矩阵中,使得其成为回文矩阵,即上下翻转左右反转和原矩阵相同。 -
解题思路
我们知道,对于 n n n为偶数的时候,其中矩阵总是四个四个对称的,所以我们只需要将这四个对称的填相同元素即可。而对于 n n n为奇数的时候,中间有一个十字,我们需要填充十字,那么条件就没有那么苛刻,中心点只需要填一个任意值,左右对称和上下对称需要填相同的元素即可。我们可以先填中心值,再填四个对称点,最后填剩下的十字。具体看AC代码。 -
AC代码
/**
*@filename:C
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-27 10:38
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000 + 5;
const int P = 1e9+7;
int n,cnt[N],x,a[22][22];
void solve(){
//先判断n是否为奇数。如果是,直接将奇数放入a[(n + 1) / 2][(n + 1) / 2]
if(n & 1){
for(int i = 1; i < N; ++ i){
if(cnt[i] & 1){
a[(n + 1) / 2][(n + 1) / 2] = i;
cnt[i] --;
break;
}
}
//将构建中间十字。
}
priority_queue<pair<int,int>,vector<pair<int,int> > > q;//利用优先队列实现。
for(int i = 1; i < N; ++ i){
if(cnt[i])q.push({cnt[i],i});
}
//构建对角。
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= n; ++ j){
if(n % 2 && (i == (n + 1) / 2 || j == (n + 1) / 2))continue;
if(!a[i][j] && !q.empty() && q.top().first >= 4){
auto x = q.top();
q.pop();
a[i][j] = a[n - i + 1][j] = a[n - i + 1][n - j + 1] = a[i][n - j + 1] = x.second;
x.first -= 4;
if(x.first)q.push(x);
}
}
}
//注意中间十字是不会变的。我们先构建中间十字。
if(n & 1){
for(int i = 1; i <= n; ++ i){
if(!a[i][(n + 1) / 2] && !q.empty() && q.top().first > 1){
auto x = q.top();
q.pop();
a[i][(n + 1) / 2] = a[n - i + 1][(n + 1) / 2] = x.second;
x.first -= 2;
if(x.first)q.push(x);
}
}
for(int j = 1; j <= n; ++ j){
if(!a[(n + 1) / 2][j] && !q.empty() && q.top().first > 1){
auto x = q.top();
q.pop();
a[(n + 1) / 2][j] = a[(n + 1) / 2][n - j + 1] = x.second;
x.first -= 2;
if(x.first)q.push(x);
}
}
}
bool flag = true;
if(!q.empty())flag = false;
if(flag){
cout << "YES" << endl;
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= n; ++ j){
cout << a[i][j] << " ";
}
cout << endl;
}
}
else{
cout << "NO" << endl;
}
}
int main(){
cin >> n;
for(int i = 1; i <= n * n; ++ i){
cin >> x;
cnt[x] ++;
}
solve();
return 0;
}
D1 D2. Coffee and Coursework
-
题意
给你 n n n杯咖啡,每杯咖啡都有一个值 a i a_i ai。当你一天内依次喝的咖啡得到的值为 a 1 , m a x ( 0 , a 2 − 1 ) . . . m a x ( 0 , a k − k + 1 ) a_1,max(0,a_2-1)...max(0,a_k-k+1) a1,max(0,a2−1)...max(0,ak−k+1)。问你需要几天才可以得到 m m m。 -
解题思路
很明显的二分题,我们知道当所有咖啡值总和小于 m m m时是一定无解的。我们又注意到,若 x x x天可行,那么 x + 1 x+1 x+1天必定可行。若 x x x天不可行,那么 x − 1 x-1 x−1天必定不可行。据此,符合二分的性质,所以我们二分天数,在计算得到的值时我们从大到小按天数依次分配即可,这样减小最大损耗。 -
AC代码
/**
*@filename:D1
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-27 11:49
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
const int P = 1e9+7;
int n,m;
ll a[N],ans;
bool check(int day){
//为了最少消耗,我们均分day。
ll ans = 0,cnt = 1,c = 0;
while(true){
for(int d = 1; d <= day && cnt <= n; ++ d){
ans += max(1LL * 0,a[cnt ++] - c);
}
c++;
if(cnt > n)break;
}
return ans >= m;
}
void solve(){
sort(a + 1, a + 1 + n,greater<int>() );
//此原理就是尽可能的浪费一些也可以行。ans为最大的数量。
if(ans < m){
cout << - 1 << endl;
}
else{
int l = 1, r = n;
while(l < r){
int mid = (l + r) >> 1;
if(check(mid)){
r = mid;
}
else{
l = mid + 1;
}
}
cout << l << endl;
}
}
int main(){
cin >> n >> m;
for(int i= 1; i <= n; ++ i){
cin >> a[i];
ans += a[i];
}
solve();
return 0;
}
E. Yet Another Ball Problem
-
题意
有 n n n对舞者,其中一男一女,设它们的服装颜色分别为 b i , g i b_i,g_i bi,gi。有 k k k种颜色的舞服。现在需要你分配一种服装方案使得:- 所有舞者的颜色都是这 k k k种之一。
- 没有一对舞者的服装一摸一样,即不会存在 i ≠ j , b i = b j a n d g i = g j i≠j,b_i=b_j \space \space and \space \space g_i=g_j i=j,bi=bj and gi=gj
- 一对舞者内的二人服装不一样。
- 相邻序号的舞者中两个男的和女的的服装不一样。即 b i ≠ b i + 1 , g i ≠ g i + 1 b_i≠b_{i+1},g_i≠g_{i+1} bi=bi+1,gi=gi+1
-
解题思路
我们知道,根据第 2 2 2点和第三点,我们能构造出来的舞者队服为 k × ( k − 1 ) k\times (k -1) k×(k−1),当其值小于 n n n时自然不可能,否则一定可行。那么我们只需要再满足第四点即可,我们可以依次构造 ( 1 , 2 ) ( 2 , 1 ) ( 1 , 3 ) ( 3 , 1 ) . . . ( i , j ) ( j , i ) (1,2)(2,1)(1,3)(3,1)...(i,j)(j,i) (1,2)(2,1)(1,3)(3,1)...(i,j)(j,i)这种即可达到要求。 -
AC代码
/**
*@filename:E
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-27 18:46
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
int n,k;
void solve(){
ll ans = 1LL * k * (k - 1);
if(ans < n){
cout << "NO" << endl;
}
else{
cout << "YES" << endl;
int idx = 1,cnt = 0;
while(true){
for(int i = idx + 1; i <= k; ++ i){
if(cnt < n){
cout << idx << " " << i << endl;
cnt ++;
}
if(cnt < n){
cout << i << " " << idx << endl;
cnt ++;
}
if(cnt == n)break;
}
idx ++;
if(cnt == n){
break;
}
}
}
}
int main(){
cin >> n >> k;
solve();
return 0;
}
F1. Tree Cutting (Easy Version)
-
题意
给你一个无向树,每个顶点都有一个点权,其中 0 0 0表示未染色, 1 1 1表示染了红色, 2 2 2表示染了蓝色。你需要删除一条边分成两个集合后,每个集合中的点只包含了一种颜色。问方案数。 -
解题思路
d f s dfs dfs遍历树,我们需要存储每个结点的子树及其本身的颜色信息。那么当这个颜色信息中只包含了一种颜色即可行。按这种思想遍历即可。 -
AC代码
/**
*@filename:F
*@author: pursuit
*@csdn:unique_pursuit
*@email: 2825841950@qq.com
*@created: 2021-07-27 19:02
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 300000 + 5;
const int P = 1e9+7;
int n,a[N],r[N],b[N];
vector<int> g[N];
ll ans;
void dfs(int u,int fu){
if(a[u] == 1){
r[u] ++;
}
else if(a[u] == 2){
b[u] ++;
}
for(auto &v : g[u]){
if(v != fu){
dfs(v,u);
//将子节点的数量加起来。
b[u] += b[v];
r[u] += r[v];
if(b[v] == b[0] && !r[v] || r[v] == r[0] && !b[v]){
ans ++;
}
}
}
}
void solve(){
dfs(1,0);
cout << ans << endl;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
scanf("%d", &a[i]);
//1:red 2:blue
//统计所有的红蓝结点数,相当于0是祖先。
if(a[i] == 1){
r[0] ++;
}
else if(a[i] == 2){
b[0] ++;
}
}
int u,v;
for(int i = 1; i < n; ++ i){
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)