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 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Codeforces Round #451 (Div. 2) 题解 -> 正文阅读

[数据结构与算法]Codeforces Round #451 (Div. 2) 题解

作者:>

A. Rounding

  • 题意

给你一个非负整数,需要你输出将其舍入到最接近的整数,且末尾是 0 0 0

/**
  *@filename:A
  *@author: pursuit
  *@created: 2021-08-12 14:05
**/
#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;
void solve(){
    int temp = n % 10;
    if(temp >= 5){
        n = n / 10 * 10 + 10;
    }
    else{
        n = n / 10 * 10;
    }
    cout << n << endl;
}
int main(){
    cin >> n;	
    solve();
    return 0;
}
  • 解题思路

    取最低位判断是否 ≥ 5 \geq5 5?即可,据此作出改变, n ÷ 10 × 10 + n ≥ 5 ? 10 : 0 n\div 10\times 10 + n\geq 5 ?10:0 n÷10×10+n5?10:0

  • AC代码

B. Proper Nutrition

  • 题意

    给你 n , a , b n,a,b n,a,b三个整数,找出是否存在 x , y x,y x,y使得 a x + b y = n ax+by=n ax+by=n

  • 解题思路

    直接暴力即可,枚举 x x x即可确定 y y y,而 n n n 1 e 7 1e7 1e7 O ( n ) O(n) O(n)复杂度可以通过。

  • AC代码

/**
  *@filename:B
  *@author: pursuit
  *@created: 2021-08-12 14:08
**/
#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,b;
void solve(){
    int maxx = n / b;
    for(int i = 0; i <= maxx; ++ i){
        int temp = n - i * b;
        if(temp % a == 0){
            cout << "YES" << endl;
            cout << temp / a << " " << i << endl;
            return;
        }
    }
    cout << "NO" << endl;
}
int main(){	
    cin >> n >> a >> b;
    solve();
    return 0;
}

C. Phone Numbers

  • 题意

    给你每个人的电话号码信息,需要你对每一个人的电话号码信息进行处理,即若甲的电话号码 x x x是甲的电话号码 y y y的后缀,那么就删除 x x x。按格式输出处理后的信息。

  • 解题思路

    好题。考察细节,对字符串的处理以及一些必要的数据存储技能。我们首先需要存储每个人的姓名以及电话信息,这里我们采用 v e c t o r vector vector存储,同时我们需要确定每个人的编号方便索引存储位置以及需要通过编号来确定姓名,这里采用了两个 m a p map map实现。当然,我们也可以只用一个结构体来实现存储。注意一定要判断每个人是否之前已经存储过了,若存储过直接在原地方存储即可。

    处理好之后,我们来分析怎么删除,如果 x x x y y y的后缀,那么第一点就是 l e n ( a ) ≤ l e n ( b ) len(a) \leq len(b) len(a)len(b)。所以我们可以先对每个人的电话号码按长度大小排序,这样能保证长度要求。那么之后就是要比较是否相等了,根据 x , y x,y x,y自然能索引到 x x x y y y中的起始判断位置,即使 l e n ( y ) ? l e n ( x ) len(y) - len(x) len(y)?len(x),故只需判断 y . s u b s t r ( l e n ( y ) ? l e n ( x ) ) = x y.substr(len(y) - len(x))=x y.substr(len(y)?len(x))=x即可。

  • AC代码

/**
  *@filename:C
  *@author: pursuit
  *@created: 2021-08-12 14:31
**/
#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 = 22 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n,cnt;
map<int,string> p1;
map<string,int> p2;
vector<string> ans[N];
string s,num;
//按字符串长度排序。
bool cmp(string a,string b){
    return a.size() < b.size();
}
void solve(){
    cout << p2.size() << endl;
    for(int i = 1; i <= cnt; ++ i){
        //处理每个人的号码。 
        sort(ans[i].begin(),ans[i].end(),cmp);
        for(int j = 0; j < ans[i].size(); ++ j){
            string num1 = ans[i][j];
            for(int k = j + 1; k < ans[i].size(); ++ k){
                string num2 = ans[i][k];
                if(num2.substr(num2.size() - num1.size()) == num1){
                    ans[i].erase(ans[i].begin() + j);
                    j --;
                    break;
                }
            }
        }   
        cout << p1[i] << " " << ans[i].size() << " ";
        for(int j = 0; j < ans[i].size(); ++ j){
            cout << ans[i][j] << " ";
        }
        cout << endl;
    }
}
int main(){
    cin >> n;
    for(int i = 1; i <= n; ++ i){
        cin >> s;
        if(!p2[s]){
            p2[s] = ++ cnt;
            p1[cnt] = s;
        }
        int id = p2[s],tot;
        cin >> tot;
        while(tot -- ){
            cin >> num;
            ans[id].push_back(num);
        }
    }	
    solve();
    return 0;
}

D. Alarm Clock

  • 题意

    给你一个 n n n时钟,其响铃时间为 a i a_i ai?,需要你至少关闭多少个闹钟才能使得连续 m m m分钟响铃次数 < k <k <k

  • 解题思路

    使劲贪即可。注意到,我们必然是 ≥ k \geq k k时再关闭,且一定是关闭触发这个条件时刻的一些闹钟,使得响铃次数变成 k ? 1 k-1 k?1,至此题解。

  • AC代码

/**
  *@filename:D
  *@author: pursuit
  *@created: 2021-08-12 15:28
**/
#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 = 1e6 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n,m,k,x;
int a[N],maxx;
ll cnt;
void solve(){
    ll ans = 0;
    for(int i = i; i <= maxx; ++ i){
        if(i < m)cnt += a[i];
        else cnt += (a[i] - a[i - m]);
        if(cnt >= k){
            ans += cnt - k + 1;
            a[i] -= (cnt - k + 1);
            cnt = k - 1;
        }
        //cout << cnt << endl;
    }
    printf("%lld\n", ans);
}
int main(){	
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 1; i <= n; ++ i){
        scanf("%d", &x);
        maxx = max(maxx,x);
        a[x] ++;
    }
    solve();
    return 0;
}

E. Squares and not squares

  • 题意

    给定 n n n个数,你可以对其中每个数进行 + ? 1 +-1 +?1操作,问使得这 n n n个数有 n / 2 n/2 n/2个非平方数和 n / 2 n/2 n/2个平方数的最少操作次数。

  • 解题思路

    对于平方数变非平方数,+1即可(0需要+2),对于非平方数变平方数,选择最近的那个即可。将这些数的消耗排序,取最小的即可。

  • AC代码

/**
  *@filename:E
  *@author: pursuit
  *@created: 2021-08-12 15:39
**/
#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 = 2e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n;
ll x;
ll a[N],b[N];
int cnta,cntb;
ll cal(ll *a,int x,int n){
    ll res = 0;
    sort(a + 1,a + 1 + n);
    for(int i = 1; i <= x; ++ i){
        //cout << a[i] << endl;
        res += a[i];
    }
    return res;
}
void solve(){
    if(cnta == cntb){
        puts("0");
    }
    else{
        printf("%lld\n",cnta > cntb ? cal(a,cnta - n / 2,cnta) : cal(b,cntb - n / 2,cntb));
    }
}
int main(){	
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i){
        scanf("%lld", &x);
        int temp = sqrt(x);
        if(temp * temp == x){
            if(x)a[++cnta] = 1;
            else a[++cnta] = 2;
        }
        else{
            b[++cntb] = min((temp + 1) * (temp + 1) - x,x - temp * temp);
        }
    }
    solve();
    return 0;
}

F. Restoring the Expression

  • 题意

    给定一个数值字符串 s s s,需要你分割成 a , b , c a,b,c a,b,c使得 a , b , c a,b,c a,b,c不包含前导零,且 a + b = c a+b=c a+b=c n ≤ 1 0 6 n\leq 10^6 n106

  • 解题思路

    注意到 n n n?的范围,所以我们需要在 O ( n ) O(n) O(n)?时间内解决。我们发现,只需要枚举 = 号的位置,而根据其合理性 m a x ( l e n A , l e n B ) ≤ l e n C ≤ m a x ( l e n A , l e n B ) + 1 max(lenA,lenB) \leq lenC \leq max(lenA,lenB) + 1 max(lenA,lenB)lenCmax(lenA,lenB)+1??,那么确定了 l e n C lenC lenC?,则有4种可能。 l e n A = l e n C , l e n B = n ? ( l e n A + l e n C ) , 同 理 l e n B = l e n C , l e n A = n ? . . . , l e n A = l e n C ? 1 , l e n B = n ? ( l e n A + l e n C ) , 同 理 l e n B = n ? . . . . lenA = lenC,lenB = n - (lenA + lenC),同理lenB = lenC,lenA = n -...,lenA = lenC - 1,lenB = n - (lenA + lenC),同理lenB = n - .... lenA=lenC,lenB=n?(lenA+lenC)lenB=lenC,lenA=n?...,lenA=lenC?1,lenB=n?(lenA+lenC)lenB=n?....?

    所以实际上我们是可以在线性时间内完成字符串的分割的,关键在于判断 a + b = c a+b=c a+b=c????,大数首先排除 O ( n 2 ) O(n^2) O(n2)????,那么有什么方法呢?这里引入 h a s h ? C o d e hash\ Code hash?Code?????,也叫散列值,就是将字符串映射成一个数值,一个数值代表一个字符串。字符串hash【算法学习】字符串哈希(Hash),大家可以看一下一些 b l o g blog blog????学习。于是如果我们比较字符串相等,那么可以直接比较它们的 h a s h ? C o d e hash\ Code hash?Code??,这样就达到了 O ( 1 ) O(1) O(1)???的字符串相等判断,即用空间换时间。字符串 h a s h hash hash??需要我们确定 b a s e base base??和 m o d mod mod??,然后对应的 h a s h hash hash??公式即为 h a s h [ i ] = ( h a s h [ i ? 1 ] × b a s e + s [ i ] ? ′ 0 ′ ) % m o d hash[i] = (hash[i - 1] \times base + s[i] - '0') \% mod hash[i]=(hash[i?1]×base+s[i]?0)%mod??,对于此方法,我们需要将 b a s e base base??和 m o d mod mod????取大一点,这样才能避免数值冲突。如果要获取字串的 h a s h hash hash??值,那么其对应公式即为 r e s = ( ) ( h a s h [ r ] ? h a s h [ l ? 1 ] × b a s e r ? l + 1 ) % m o d + m o d ) % m o d ( 由 于 是 减 法 , 所 以 可 能 是 负 值 , 需 要 + m o d 取 余 res = ()(hash[r] - hash[l -1] \times base^{r-l+1})\% mod + mod)\%mod(由于是减法,所以可能是负值,需要+mod取余 res=()(hash[r]?hash[l?1]×baser?l+1)%mod+mod)%mod(+mod?)$????

    那么这里还需提到的一点就是如何得到 a + b a+b a+b???,就是直接散列值相加即可,因为每个值可以唯一代表一个字符串。

    h a s h hash hash算法各种各样,能写出适合自己的 h a s h hash hash模板即可。

  • AC代码

/**
  *@filename:F
  *@author: pursuit
  *@created: 2021-08-12 15: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 = 1e6 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n;
int base = 10;//base为基底,其代表了为几进制数。
ll Hash[N],p[N];
string s;  
//字符串hash,写法有很多种。
//不过思路都是一样的,就是要用唯一的数值确定一段字符串。所以也跟mod有关。
void init(){
    n = s.size();
    for(int i = 0; i < n; ++ i){
        Hash[i + 1] = (Hash[i] * base % P + s[i] - '0') % P;
    }
    p[0] = 1;//base ^ i
    for(int i = 0; i < n; ++ i){
        p[i + 1] = p[i] * base % P;
    }
}
int get(int l,int r){
    //获取[l,r]子串。
    if(r < 0 || l - 1 < 0 || r - l + 1 < 0)return 0;
    return (Hash[r] - Hash[l - 1] * p[r - l + 1] % P + P) % P;
}
bool check(int lenA,int lenB,int lenC){
    if(lenA > lenC || lenB > lenC)return false;
    if(lenA < 0 || lenB < 0)return false;
    if(s[lenA] == '0' && lenB != 1)return false;
    if(s[0] == '0' && lenA != 1)return false;
    if((get(1,lenA) + get(lenA + 1,lenA + lenB)) % P != get(lenA + lenB + 1,n)){
        return false;
    }
    return true;
}
void print(int lenA,int lenB,int lenC){
    for(int i = 0; i < lenA; ++ i){
        putchar(s[i]);
    }
    putchar('+');
    for(int i = lenA; i < lenA + lenB; ++ i){
        putchar(s[i]);
    }
    putchar('=');
    for(int i = lenA + lenB; i < n; ++ i){
        putchar(s[i]);
    }
}
void solve(){
    for(int lenC = 1; lenC < n; ++ lenC){
        if(s[n - lenC] == '0' && lenC > 1)continue;//排除前导0的情况。
        //cout << lenC << endl;
        if(check(lenC,n - 2 * lenC,lenC)){
            print(lenC,n - 2 * lenC,lenC);
            break;
        }
        else if(check(n - 2 * lenC,lenC,lenC)){
            print(n - 2 * lenC,lenC,lenC);
            break;
        }
        else if(check(lenC - 1,n - 2 * lenC + 1,lenC)){
            print(lenC - 1,n - 2 * lenC + 1,lenC);
            break;
        }
        else if(check(n - 2 * lenC + 1,lenC - 1,lenC)){
            print(n - 2 * lenC + 1,lenC - 1,lenC);
            break;
        }
    }
}
int main(){
    cin >> s;
    init();
    solve();
    return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-13 12:32:05  更:2021-08-13 12:34:05 
 
开发: 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/25 20:32:20-

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