IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Codeforces Round #522 (Div. 2) A~E题解 -> 正文阅读

[C++知识库]Codeforces Round #522 (Div. 2) A~E题解

作者:token macro property

A. Kitchen Utensils

  • 题意

    k k k个人,你需要给每个人分配一套餐具。现在剩下 n n n个餐具( a i a_i ai?代表其种类),问至少被偷走多少餐具才够分。

  • 解题思路

    对于每个人,分到的肯定是完整的一套餐具,所以总共的餐具数量一定是整除 k k k的,更严格的说,每一个种类的餐具数量都要能整除 k k k,且题目中限制了每个种类的餐具数量都相同。所以我们只需要找到数量最多的种类餐具即可。

  • AC代码

/**
  *@filename:A
  *@author: pursuit
  *@created: 2021-08-31 13:27
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 100 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n,k,x,a[N];
void solve(){
    int cnt = 0, ans = 0;
    for(int i = 1; i < N; ++ i){
        cnt += (a[i] != 0);
        ans = max(ans,a[i]);
    }
    //ans需要整分给每个人。
    ans = (ans + k - 1) / k * k;
    printf("%d\n", cnt * ans - n);
}
int main(){	
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; ++ i){
        scanf("%d", &x);
        ++ a[x];
    }
    solve();
    return 0;
}

B. Personalized Cup

  • 题意

    给定一个字符串,你需要将其分成一个矩形,使得行 ≤ 5 \leq 5 5,列 ≤ 20 \leq 20 20。你可以补充任意的*字符,但必须满足相邻两行的*字符数量相差 ≤ 1 \leq 1 1。请你构造出这样的矩形。

  • 解题思路

    我们可以枚举行,从而可以确定列。那么怎么确定行列才可行呢?必然是使得需要添加的*最小最优,所以我们选择能填充的最小矩形,即 l e n / n + ( l e n % n ! = 0 ) len / n+(len \% n != 0) len/n+(len%n!=0)。那么易知,其数量不会超过行数,所以如果有我们则可以每行填一个即可。

  • AC代码

/**
  *@filename:B
  *@author: pursuit
  *@created: 2021-08-31 13:55
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n,m,len;
char s[N];
void solve(){
    //确定行列即可。
    len = strlen(s + 1);
    for(n = 1; n <= 5; ++ n){
        m = len / n + (len % n != 0);
        if(n <= 5 && m <= 20)break;
    }
    int cnt = n * m - len, idx = 1;//需要填充的*号。
    printf("%d %d\n", n, m);
    for(int i = 1; i <= n; ++ i){
        for(int j = 1; j <= m - (cnt != 0); ++ j){
            printf("%c", s[idx ++]);
        }
        if(cnt){
            printf("*");
            -- cnt;
        }
        puts("");
    }
}
int main(){	
    scanf("%s", s + 1);
    solve();
    return 0;
}

C. Playing Piano

  • 题意

    给你一个 a a a序列,需要你构造出一个 b b b序列,使得:如果 a i < a i + 1 , 则 b i < b i + 1 a_i < a_{i + 1},则b_i < b_{i + 1} ai?<ai+1?bi?<bi+1?;如果 a i > a i + 1 , 则 b i > b i + 1 a_i > a_{i + 1},则b_i > b_{i + 1} ai?>ai+1?bi?>bi+1?;如果 a i = a i + 1 , 则 b i ! = b i + 1 a_i = a_{i + 1},则b_i != b_{i + 1} ai?=ai+1?bi?!=bi+1? b i b_i bi?取值范围为 [ 1 , 5 ] [1,5] [1,5]

  • 解题思路

    观察此题易知,当前构造的 b i b_i bi?只与 b i ? 1 b_{i-1} bi?1?的值有关系,即由 b i ? 1 b_{i-1} bi?1?转移过来的。所以这个过程我们是可以通过 d p dp dp实现的,但我们无需考虑最优解,只是状态的转移计算而已。

    我们可以用 d p [ i ] [ j ] dp[i][j] dp[i][j]表示前 i i i个且第 i i i个填 j j j的合法情况。为 0 0 0代表不可行,否则可行。

    据此题易解。注意路径的记录,我们可以用 p r e [ i ] [ j ] pre[i][j] pre[i][j]表示状态为 d p [ i ] [ j ] dp[i][j] dp[i][j]的前一个状态取的值。

  • AC代码

/**
  *@filename:C
  *@author: pursuit
  *@created: 2021-08-31 14:06
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n,a[N];
bool dp[N][10];//dp[i][j]表示前i个且第i个填j的合法情况。为0代表不可行,否则可行。
int pre[N][10];//pre[i][j]表示该状态前一个填的是什么值。
int Stack[N],top;
void solve(){
    for(int j = 1; j <= 5; ++ j){
        dp[1][j] = 1;
    }
    for(int i = 2; i <= n; ++ i){
        for(int j = 1; j <= 5; ++ j){
            if(dp[i - 1][j]){
                if(a[i] > a[i - 1]){
                    //则b[i] > b[i - 1]。
                    for(int k = j + 1; k <= 5; ++ k){
                        dp[i][k] = true, pre[i][k] = j;
                    }
                }
                else if(a[i] == a[i - 1]){
                    //则b[i] != b[i - 1]。
                    for(int k = 1; k <= 5; ++ k){
                        if(k != j){
                            dp[i][k] = true, pre[i][k] = j;
                        }
                    }
                }
                else{
                    //则b[i] < b[i - 1]。
                    for(int k = 1; k < j; ++ k){
                        dp[i][k] = true, pre[i][k] = j;
                    }
                }
            }
        }
    }
    int x = -1;
    for(int j = 1; j <= 5; ++ j){
        if(dp[n][j]) x = j;//找到合法状态。
    }
    if(x == -1){
        puts("-1");
    }
    else{
        top = 0;
        for(int i = n; i >= 1; -- i){
            Stack[top ++] = x;
            x = pre[i][x];
        }
        for(int i = top - 1; i >= 0; -- i){
            printf("%d ", Stack[i]);
        }
        puts("");
    }
}
int main(){	
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i){
        scanf("%d", &a[i]);
    }
    solve();
    return 0;
}

D. Barcelonian Distance

  • 题意

    给你一条直线 a x + b y + c = 0 ax+by+c=0 ax+by+c=0、起点坐标和终点坐标。你可以沿着坐标轴方向行走,在直线上你也可以沿着直线走。问从起点到终点的最短距离。

  • 解题思路

    当不通过直线的时候,最短距离就是曼哈顿距离。而如果通过直线,意味着我们可以走斜线,在直线上自然只有一种方式,但我们如果到达直线,如果从直线上到达终点,这里要分四种情况:起点从从y轴到达直线上或从x轴到达直线上。终点同理。我们求出在直线上的两个坐标即可。

    注意特判,当a为0或者b为0的时候,此时就是一条直线,就是曼哈顿距离。

  • AC代码

/**
  *@filename:D
  *@author: pursuit
  *@created: 2021-08-31 15:09
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
#define x first
#define y second
using namespace std;

typedef pair<double,double> pdd;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

double a,b,c;
pdd st,ed;
double getDist1(pdd a, pdd b){
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
double getDist2(pdd a, pdd b){
    return abs(a.x - b.x) + abs(a.y - b.y);
}
void solve(){
    //不通过直线,直接曼哈顿距离。
    double minn = getDist2(st,ed),ans;
    //起点通过y轴到达直线,终点通过y轴到达直线。
    //ax + by + c = 0,y = -(ax + c) / b, x = -(by + c) / a
    if(a != 0 && b != 0){
        pdd new_st(st.x,(-1) * (a * st.x + c) / b), new_ed(ed.x,(-1) * (a * ed.x + c) / b);
        ans = getDist1(new_st, new_ed) + getDist1(st, new_st) + getDist1(ed, new_ed);
        minn = min(ans, minn);
        //起点通过y轴到达直线,终点通过x轴到达直线。
        new_st = pdd(st.x,(-1) * (a * st.x + c) / b), new_ed = pdd((-1) * (b * ed.y + c) / a, ed.y);
        ans = getDist1(new_st, new_ed) + getDist1(st, new_st) + getDist1(ed, new_ed);
        minn = min(ans, minn);
        //起点通过x轴到达直线,终点通过y轴到达直线。
        new_st = pdd((-1) * (b * st.y + c) / a, st.y), new_ed = pdd(ed.x, (-1) * (a * ed.x + c) / b);
        ans = getDist1(new_st, new_ed) + getDist1(st, new_st) + getDist1(ed, new_ed);
        minn = min(ans, minn);
        //起点通过x轴到达直线,终点通过x轴到达直线。
        new_st = pdd((-1) * (b * st.y + c) / a, st.y), new_ed = pdd((-1) * (b * ed.y + c) / a, ed.y);
        ans = getDist1(new_st, new_ed) + getDist1(st, new_st) + getDist1(ed, new_ed);
        minn = min(ans, minn);
    }
    printf("%.8lf\n", minn);
}
int main(){	
    scanf("%lf%lf%lf", &a, &b, &c);
    scanf("%lf%lf%lf%lf", &st.x, &st.y, &ed.x, &ed.y);
    solve();
    return 0;
}

E. The Unbearable Lightness of Weights

  • 题意

    n n n个砝码,你不知道每个砝码多重,你只知道它们有 a 1 , a 2 , a 3 … a n a_1,a_2,a_3\dots a_n a1?,a2?,a3?an?。但是你的朋友知道,你可以每次拿出 k k k个砝码给你的朋友,他会告诉你 k k k个砝码的重量和,经过 1 1 1次尝试之后,你最多可以区分出多少个砝码?

  • 解题思路

    首先我们需要清楚的一件事就是我们选取砝码一定是选取砝码重量相同且砝码重量总和唯一的,这样才能保证我们唯一确定且知晓每个砝码多重。所以我们即是判定砝码重量总和唯一且砝码数量最多的是哪个?我们则可以先处理出砝码的重量种类以及对应数量。

    这题很类似求 i i i个物品体积为 j j j的方案数,即分组背包问题。我们可以用 d p [ i ] [ j ] dp[i][j] dp[i][j]来表示前 i i i个物品且体积为 j j j的方案数,若方案数唯一则可行。

    据此进行状态转移即可。

    注意特判砝码种类只有两个的情况,因为这我们只需要挑出最大的那个且值相同的组合,这样确定了该组,另一组也唯一确定了。

  • AC代码

/**
  *@filename:E
  *@author: pursuit
  *@created: 2021-08-31 16:23
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e4 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

//只能选相同的值才可以确定。
int n,x,cnt[N],dp[105][N];//dp[i][j]表示前i个物品且体积为j的方案数。
vector<pii> v;
void solve(){
    for(int i = 1; i <= 100; ++ i){
        if(cnt[i])v.push_back({i, cnt[i]});//将占用体积和数量放入。
    }
    dp[0][0] = 1;
    for(auto iter : v){
        int w = iter.first, num = iter.second;
        //cout << w << " " << num << endl;
        //注意先枚举体积。
        for(int j = N - 1; j > 0; -- j){
            for(int i = 1; i <= n; ++ i){
                for(int k = 1; k <= num && k * w <= j && k <= i; ++ k){
                    dp[i][j] += dp[i - k][j - k * w];
                }
            }
        }
    }
    if(v.size() == 2){
        //只有两种
        printf("%d\n", n);
    }
    else{
        int ans = 1;
        for(auto iter : v){
            int w = iter.first, num = iter.second;
            for(int i = 1; i <= num; ++ i){
                if(dp[i][i * w] == 1){
                    ans = max(ans, i);
                }
            }
        }
        printf("%d\n", ans);
    }
}
int main(){	
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i){
        scanf("%d", &x);
        ++ cnt[x];
    }
    solve();
    return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-03 11:43:10  更:2021-09-03 11:43:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:30:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码