Codeforces Round #479 (Div. 3) 题解

A. Wrong Subtraction

  • 题意

定义一种操作如下

  • 如果数字的最后一位是非0的,则该数字减少1;
  • 如果数字的最后一位是零,则把数字除以10(即去掉最后一位)。

给你一个整数 n。 你需要对这个数操作 k 次。算出最后的结果。
保证最后结果是一个整数。

  • 解题思路
    直接模拟即可。注意用字符串处理更加方便。
  • AC代码
/**
  *@filename:B
  *@author: pursuit
  *@created: 2021-08-08 19:01
**/
#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 k;
string s;
void solve(){
    int len = s.size();
    for(int i = 0; i < k; ++ i){
        if(len > 0){
            if(s[len - 1] != '0'){
                s[len - 1] -= 1;
            }
            else{
                len --;
            }
        }
    }
    for(int i = 0; i < len; ++ i){
        cout << s[i];
    }
    cout << endl;
}
int main(){
    cin >> s >> k;	
    solve();
    return 0;
}

B. Two-gram

  • 题意
    给你一个字符串,找出字符串中的频繁字串。频繁字串定义为:
    1.子串必须由相邻的两个字符组成。
    2.频繁子串是指字符串中出现次数最多的子串,注意子串可以重叠(例如字符串“BBAABBBA”,子串“BB”出现了三次)。

  • 解题思路
    由于 n n n很小,直接枚举相邻字串,再找其出现次数,保留次数最多的字串即可。

  • AC代码

/**
  *@filename:C
  *@author: pursuit
  *@created: 2021-08-08 19:04
**/
#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;
string s;
void solve(){
    string temp;
    string result;
    int maxx = 0;
    for(int i = 0; i < n - 1; ++ i){
        temp = s.substr(i,2);
        int cnt = 0;
        for(int j = 0; j < n - 1; ++ j){
            if(s.substr(j,2) == temp)cnt ++;
        }
        if(cnt > maxx){
            maxx = cnt;
            result = temp;
        }
    }
    cout << result << endl;
}
int main(){
    cin >> n >> s;	
    solve();
    return 0;
}

C. Less or Equal

  • 题意
    给你一个序列 a a a,其中元素范围为 [ 1 , 1 0 9 ] [1,10^9] [1,109],你需要确定一个正整数 x x x,使得序列 a a a中有 k k k个元素小于等于 x x x

  • 解题思路
    直接根据值来改变 x x x即可,先让 x x x取最小值 1 1 1,对排序好的数组 a a a遍历,判断是否可行,如果不可行,改变 x x x的值再判断。

  • AC代码

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

int n,k,a[N];
void solve(){
    sort(a + 1,a + 1 + n);
    int x = 1;
    int cnt = 0;
    bool flag = true;
    for(int i = 1; i <= n; ++ i){
        if(a[i] <= x){
            cnt ++;
        }
        else{
            if(cnt == k){
                if(i == n || (i < n && a[i + 1] != x)){
                    printf("%d\n", x);
                    return;
                }
                else{
                    flag = false;
                    break;
                }
            }
            else if(cnt > k){
                flag = false;
                break;
            }
            else{
                x = a[i];
                cnt ++;
            }
        }
    }
    if(!flag || cnt != k){
        printf("-1\n");
    }
    else{
        printf("%d\n", x);
    }
}
int main(){	
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; ++ i){
        scanf("%d", &a[i]);
    }
    solve();
    return 0;
}

D. Divide by three, multiply by two

  • 题意
    小明同学喜欢玩数字。他在黑板上写下一个数字 x ,然后进行 n-1 次以下两种操作(每次操作选择其中一种):

    • x 除以3 (必须能整除才能进行,即 x mod 3=0)
    • x 乘以2

    每次操作完成后,小明同学在黑板上写上这个操作后的新数字,并让这个新数字作为新的 x 继续下一次操作。最后黑板上有 n 个数字。
    由于小明同学是随机在黑板上的位置写数字的,所以他最后忘记了顺序。现在小明同学只知道所有的数字,你能帮助小明同学找出一种可能的序列吗?

  • 解题思路
    由于 n n n很小,且操作具有局限性,并且每个数都是唯一的。所以我们可以直接 d f s dfs dfs枚举找到符合情况的序列。

  • AC代码

/**
  *@filename:E
  *@author: pursuit
  *@created: 2021-08-08 19:14
**/
#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;
vector<ll> a;
map<ll,int> p;
void dfs(int i,vector<ll> ans,int cnt){
    //debug(ans[i]);
    if(cnt == n){
        for(int j = 1; j < ans.size(); ++ j){
            printf("%lld ", ans[j]);
        }
        puts("");
        return;
    }
    for(int op = 0; op < 2; ++ op){
        if(op == 0 && ans[i] % 3 == 0 && p[ans[i] / 3]){
            ans.push_back(ans[i] / 3);
            dfs(i + 1,ans,cnt + 1);
            ans.pop_back();
        }
        else if(op == 1 && p[2 * ans[i]]){
            ans.push_back(ans[i] * 2);
            dfs(i + 1, ans,cnt + 1);
            ans.pop_back();
        }
    }
}
void solve(){
    sort(a.begin(),a.end());
    bool flag = false;
    vector<ll> temp;
    temp.push_back(0);
    for(int i = 1; i <= n; ++ i){
        temp.push_back(a[i]);
        dfs(1,temp,1);
        temp.pop_back();
        if(flag)break;
    }
}
int main(){
    scanf("%d", &n);
    a.resize(n + 1);
    for(int i = 1; i <= n; ++ i){
        scanf("%lld", &a[i]);
        p[a[i]] = i;
    }	
    solve();
    return 0;
}

E. Cyclic Components

  • 题意
    给你一个无向图,找出有多少个简单环。

在这里插入图片描述

  • 解题思路
    不难发现,简单环有一个独特的性质,即所有点的度都为 2 2 2。所以我们可以利用这个性质 d f s dfs dfs去一条路径找有没有符合度都为 2 2 2的点即可。

  • AC代码

/**
  *@filename:E
  *@author: pursuit
  *@created: 2021-08-08 19:14
**/
#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;
vector<ll> a;
map<ll,int> p;
void dfs(int i,vector<ll> ans,int cnt){
    //debug(ans[i]);
    if(cnt == n){
        for(int j = 1; j < ans.size(); ++ j){
            printf("%lld ", ans[j]);
        }
        puts("");
        return;
    }
    for(int op = 0; op < 2; ++ op){
        if(op == 0 && ans[i] % 3 == 0 && p[ans[i] / 3]){
            ans.push_back(ans[i] / 3);
            dfs(i + 1,ans,cnt + 1);
            ans.pop_back();
        }
        else if(op == 1 && p[2 * ans[i]]){
            ans.push_back(ans[i] * 2);
            dfs(i + 1, ans,cnt + 1);
            ans.pop_back();
        }
    }
}
void solve(){
    sort(a.begin(),a.end());
    bool flag = false;
    vector<ll> temp;
    temp.push_back(0);
    for(int i = 1; i <= n; ++ i){
        temp.push_back(a[i]);
        dfs(1,temp,1);
        temp.pop_back();
        if(flag)break;
    }
}
int main(){
    scanf("%d", &n);
    a.resize(n + 1);
    for(int i = 1; i <= n; ++ i){
        scanf("%lld", &a[i]);
        p[a[i]] = i;
    }	
    solve();
    return 0;
}

F. Consecutive Subsequence

  • 题意
    给定一个长度为 n n n 的整数序列。
    请找出最长的递增的连续子序列,子序列的形式如下: [ x , x + 1 , … , x + k − 1 ] [ x , x+1 , … , x+k−1] [x,x+1,,x+k1] (子序列长度为 k k k)。

  • 解题思路
    简单 d p dp dp,我们可以用 m a p map map来记录每个值前面的最长序列长度。那么状态转移方程自然是 p [ x ] = p [ x − 1 ] + 1 p[x] = p[x-1]+1 p[x]=p[x1]+1。这样我们只需要保存最大长度以及最后一个元素即可,最后利用这个元素去从后往前遍历 a a a数组,得到元素的下标。

  • AC代码

/**
  *@filename:G
  *@author: pursuit
  *@created: 2021-08-08 20:14
**/
#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 a[N];
map<int, int> p;
int main(){
    int n;
    cin >> n;
    int maxx = 0, last;
    for(int i = 1;i <= n; i++){
        int temp;
        cin >> temp;
        a[i] = temp;
        p[temp] = p[temp - 1] + 1;
        if(p[temp] > maxx){
            maxx = p[temp];
            last = temp;
        }
    }
    vector<int> ans;
    for(int i = n; i >= 1; -- i){
        if(a[i] == last){
            ans.push_back(i);
            last--;
        }
    }
    cout << maxx << endl;
    for(int i = ans.size() - 1; i >= 0; -- i){
        cout << ans[i] << ' ';
    }
}
posted @ 2022-03-26 16:48  unique_pursuit  阅读(76)  评论(0)    收藏  举报