传送门

A Wrong Subtraction

#include<bits/stdc++.h>

#define int long long

using namespace std;

const int N = 200010;

int a[N], b[N];

void solve() {
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        string s = to_string(n);
        if (s[s.size() - 1] == '0')n /= 10;
        else n--;
    }
    cout << n << endl;
}

int32_t  main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int h_h;
    //cin >> h_h;
    h_h=1;
    while (h_h--)solve();
    return 0;
}

B Two-gram

数据范围较小,直接暴力枚举即可

#include<bits/stdc++.h>

#define int long long

using namespace std;

const int N = 200010;

int a[N], b[N];

void solve() {
   int n;
   string s;
   cin >> n >> s;
   int mx = 0;
   string str;
   for (int i = 0; i < n; i++) {
       string s1 = s.substr(i, 2);
       int ans = 0;
       for (int j = 0; j < n; j++) {
           if (s1 == s.substr(j, 2))ans++;
       }
       if (mx < ans) {
           mx = ans;
           str = s1;
       }
   }
   cout << str << endl;
}

int32_t  main() {
   ios::sync_with_stdio(false);
   cin.tie(nullptr), cout.tie(nullptr);
   int h_h;
   //cin >> h_h;
   h_h = 1;
   while (h_h--)solve();
   return 0;
}

C Less or Equal

#include<bits/stdc++.h>

#define int long long

using namespace std;

const int N = 200010, M = 1e9;

int a[N], b[N];

map <int,int> mp;

void solve() {
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++)cin >> a[i], mp[a[i]]++;
    sort(a, a + n);
    int sum = 0;
    //for(auto &[f,s]: mp)cout<<f<<' '<<s<<endl;
    if (m == 0) {
        if (a[0] == 1) {
            cout << -1 << endl;
            return;
        } else {
            cout << 1 << endl;
            return;
        }
    }
    for (auto &[f, s]: mp) {
        sum += s;
        if (sum == m) {
            cout << f << endl;
            return;
        } else if (sum > m) {
            cout << -1 << endl;
            return;
        }
    }
}

int32_t  main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int h_h;
    //cin >> h_h;
    h_h = 1;
    while (h_h--)solve();
    return 0;
}

D Divide by three, multiply by two

可以直接把所有满足条件的两个数字之间建一条单向边,因为保证一定有解,所以对每个点都跑一遍dfs,只要ans数组里的数达到n个,就输出并且退出程序即可。

#include<bits/stdc++.h>

#define int long long

using namespace std;

const int N = 10010;

int h[N], e[N], ne[N], idx;
int n;
int edge[N];
bool vis[N];
vector<int> ans;

void add (int a,int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u) {
    if (ans.size() == n) {
        for (auto i: ans)cout << i << ' ';
        exit(0);
    }
    vis[u] = true;
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (!vis[j]) {
            vis[j] = true;
            ans.push_back(edge[j]);
            dfs(j);
            ans.pop_back();
            vis[j] = false;
        }
    }
}

int32_t main() {
    memset(h, -1, sizeof h);
    cin >> n;
    for (int i = 0; i < n; i++)cin >> edge[i];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (edge[i] * 2 == edge[j] || edge[i] == edge[j] * 3) {
                add(i, j);
            }
        }
    }
    for (int i = 0; i < n; i++) {
        memset(vis, false, sizeof vis);
        ans.clear();
        ans.push_back(edge[i]);
        dfs(i);
    }
    return 0;
}

这个题也可以使用拓扑序列来做,因为有解,一定可以保证有拓扑序列,然后跑一边拓扑序列即可

#include<bits/stdc++.h>

#define int long long

using namespace std;

const int N = 10010;

int h[N], e[N], ne[N], idx;
int n;
int edge[N];
bool vis[N];
vector<int> ans;
int indg[N];

void add (int a,int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void topsort() {
    queue<int> q;
    for (int i = 0; i < n; i++) {
        if (indg[i] == 0)q.push(i);
    }
    while (q.size()) {
        auto t = q.front();
        q.pop();
        ans.push_back(edge[t]);
        for (int i = h[t]; ~i; i = ne[i]) {
            int j = e[i];
            indg[j]--;
            if (indg[j] == 0)q.push(j);
        }
    }
}

int32_t main() {
    memset(h, -1, sizeof h);
    cin >> n;
    for (int i = 0; i < n; i++)cin >> edge[i];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (edge[i] * 2 == edge[j] || edge[i] == edge[j] * 3) {
                add(i, j);
                indg[j]++;
            }
        }
    }
    topsort();
    for(auto i:ans)cout<<i<<' ';
    return 0;
}

E Cyclic Components

题目要救求解一个单环,意思就是每条边的度为2,那么我们可以用dfs来找出答案,dfs的时候判断一下,只有没有被标记过并且度为2的才可以进行搜索,只要搜索过程中出现度不为2的边,就标记,只要出现了就代表不行,否则就让答案++

#include<bits/stdc++.h>

//#define int long long

using namespace std;

const int N = 2000010;

int n, m;
int indg[N];
bool vis[N];
int h[N],e[N],ne[N],idx;
bool ok;
int ans;

void add(int a,int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u) {
    vis[u] = true;
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (!vis[j]) {
            if (indg[j] == 2)dfs(j);
            else ok = false;
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr),cout.tie(nullptr);
    memset(h, -1, sizeof h);
    cin >> n >> m;
    while (m--) {
        int a, b;
        cin >> a >> b;
        add(a, b);
        add(b, a);
        indg[a]++, indg[b]++;
    }
    for (int i = 1; i <= n; i++) {
        if (!vis[i] && indg[i] == 2) {
            ok = true;
            dfs(i);
            if (ok)ans++;
        }
    }
    //for (int i = 1; i <= n; i++)cout << indg[i] << ' ';
    //puts("");
    cout << ans << endl;
    return 0;
}

也可以使用并查集来维护连通性,先预处理每条边的度数,然后再遍历一遍,只要两个点不在一个集合并且度数都为2就合并,如果两个点在一个集合当中,说明这两条再连在一起就成环了,答案++

#include<bits/stdc++.h>

//#define int long long

using namespace std;

const int N = 400010;

int n, m;
int indg[N];
bool vis[N];
int h[N],e[N],ne[N],idx;
bool ok;
int ans;

void add(int a,int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u) {
    vis[u] = true;
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (!vis[j]) {
            if (indg[j] == 2)dfs(j);
            else ok = false;
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr),cout.tie(nullptr);
    memset(h, -1, sizeof h);
    cin >> n >> m;
    while (m--) {
        int a, b;
        cin >> a >> b;
        add(a, b);
        add(b, a);
        indg[a]++, indg[b]++;
    }
    for (int i = 1; i <= n; i++) {
        if (!vis[i] && indg[i] == 2) {
            ok = true;
            dfs(i);
            if (ok)ans++;
        }
    }
    //for (int i = 1; i <= n; i++)cout << indg[i] << ' ';
    //puts("");
    cout << ans << endl;
    return 0;
}

F Consecutive Subsequence

这题就是一个最长上升子序列的题目,只不过要求更加严格,要求每一个都比前一个大1,我们可以在dp的过程中就记录最大长度以及所对应的最后一个数值,方便再最后输出下标,最后输出下标就倒着遍历一遍,把答案放进vector中,最后翻转一下即可

#include<bits/stdc++.h>

#define int long long

using namespace std;

const int N = 200010, M = 1e9;

map<int,int> dp;
int n;
int a[N];
int ans,pos;

void solve() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        dp[a[i]] = dp[a[i] - 1] + 1;
        if (ans < dp[a[i]]) {
            ans = dp[a[i]];
            pos = a[i];
        }
    }
    //cout << ans << ' ' << pos << endl;
    //for (auto i: dp)cout << i.first << ' ' << i.second << endl;
    //cout << endl;
    vector<int> b;
    cout << ans << endl;
    for (int i = n - 1; i >= 0; i--) {
        if (pos == a[i]) {
            b.push_back(i + 1);
            pos--;
        }
    }
    reverse(b.begin(), b.end());
    for (auto i: b)cout << i << ' ';
}

int32_t  main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int h_h;
    //cin >> h_h;
    h_h = 1;
    while (h_h--)solve();
    return 0;
}