传送门

A. 签到啦

排个序每次选最大的

#include<bits/stdc++.h>

#define int long long
#define endl '\n'
#define fi first
#define se second

using namespace std;

const int N =100010;

int a[N],b[N];
int n, m;

void solve() {
    cin >> n >> m;
    for (int i = 0; i < n; i++)cin >> a[i];
    sort(a, a + n, greater<int>());
    int cnt = 0;
    for (int i = 0; i < n; i++) {
        cnt += a[i];
        if (cnt >= m) {
            cout << i + 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 = 13;
    while (h_h--)solve();
    return 0;
}

Problem B. 熙巨打票

将操作实际和冷却时间打包,但是在两台机器打印最后一张的时候去除冷却时间即可,咬住以如果冷却时间小于打印时间要另外计算

#include<bits/stdc++.h>

#define int long long
#define endl '\n'
#define fi first
#define se second

using namespace std;

const int N =100010;

int a[N],b[N];
int n, m;

void solve() {
    int a, b, n;
    cin >> a >> b >> n;
    if (b >= a) {
        cout << b * n << endl;
        return;
    }
    if (n & 1) {
        int x = n / 2;
        cout << x * (a + b) + b << endl;
    } else {
        int x = n / 2 - 1;
        cout << x * (a + b) + b + b << endl;
    }
}

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

C. 三元分配

分情况讨论,要使两辆配对,则总和必须是偶数,又分为全是偶数和两个奇数和一个偶数,全是偶数一定可以两两配对,而如果有奇数的话,就需要偶数和其中的两个奇数的额和都是质数,还有两种特殊情况,偶数为零的话只能考虑另外两个奇数的和是不是质数,还有另外两个奇数唯一就肯定可以分配,赛时没考虑零的情况wa了很多发

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
bool vis[N];
int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int T;
    cin >> T;
    vis[1] = 1;
    for (int i = 2; i <= N; i++) {
        if (!vis[i]) {
            for (int j = i + i; j <= N; j += i) {
                vis[j] = 1;
            }
        }
    }
    while (T--) {
        int a, b, c;
        cin >> a >> b >> c;
        if ((a + b + c) % 2 != 0) cout << 'P' << '\n';
        else {

            if (a % 2 == 0 && b % 2 == 0 && c % 2 == 0)cout << 'R' << '\n';
            else if (a % 2 == 0) {
                if (a == 0) {
                    if (!vis[c + b])cout << 'R' << endl;
                    else cout << 'P' << '\n';
                } else if (b + c == 2) cout << 'R' << '\n';
                else if (!vis[a + b] && !vis[a + c])cout << 'R' << '\n';
                else cout << 'P' << '\n';
            } else if (b % 2 == 0) {
                if (b == 0) {
                    if (!vis[a + c])cout << 'R' << endl;
                    else cout << 'P' << '\n';
                } else if (a + c == 2) cout << 'R' << '\n';
                else if (!vis[a + b] && !vis[b + c])cout << 'R' << '\n';
                else cout << 'P' << '\n';
            } else if (c % 2 == 0) {
                if (c == 0) {
                    if (!vis[a + b])cout << 'R' << endl;
                    else cout << 'P' << '\n';
                } else if (b + a == 2) cout << 'R' << '\n';
                else if (!vis[a + c] && !vis[b + c])cout << 'R' << '\n';
                else cout << 'P' << '\n';
            }
        }
    }
    return 0;
}

Problem D. "逆"天求和

主要就是读题,读懂题推出公式,就可以了,如果没有读懂公式可以通过打表找规律,因为如果直接求逆元会超时,可以先用快速幂求逆元,求出小范围的数据,从中找规律。

打表代码

#include<bits/stdc++.h>

#define int long long
#define endl '\n'
#define fi first
#define se second

using namespace std;

const int N =100010;

int f[]{2,3,5,7,11,13,17,19,23,31,37};
int tt=0;

int qkpow(int a,int b,int mod){
    int res = 1, t = a % mod;
    while(b){
        if(b & 1)
            res = (res * t) % mod;
        t = (t * t) % mod;
        b >>= 1;
    }
    return res;
}
void solve() {
    int n = f[tt++];
    int sum = 0;
    for (int i = 1; i < n; i++) {
        sum += qkpow(i, n - 2, n);
    }
    cout << sum << ' ' << n << endl;
}

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

/*
1 2
3 3
10 5
21 7
55 11
78 13
136 17
171 19
253 23
465 31
*/

公式就是1到n-1的和,直接就是n*(n-1)/2;

#include<bits/stdc++.h>

#define int long long
#define endl '\n'
#define fi first
#define se second

using namespace std;

const int N =100010;
void solve() {
   int n;
   cin >> n;
   int sum =  0;
   cout << n*(n-1)/2 << 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;
}

Problem E. 读中国数字

模拟题,注意把数字按照四个四个的操作即可,注意细节

#include<bits/stdc++.h>

//#define int long long
#define endl '\n'
#define fi first
#define se second

using namespace std;

const int N = 100010;

map<int,char> mp;
map<int,char> mp1;

void solve() {
    string s;
    cin >> s;
    if (s == "0") {
        cout << 0 << endl;
        return;
    }
    string str;
    mp[0] = 'K', mp[1] = 'B', mp[2] = 'T', mp[3] = '-';
    vector<string> ans;
    for (int i = (int) s.size() - 1; i >= 0; i--) {
        str += s[i];
        if (str.size() == 4) {
            reverse(str.begin(), str.end());
            ans.push_back(str), str.clear();
        }
    }
    if ((int) str.size()) {
        reverse(str.begin(), str.end());
        ans.push_back(str);
    }
    reverse(ans.begin(), ans.end());
    //for (auto i: ans)cout << i << ' ';cout<<endl;
    string sans;
    //cout << ans.size() << endl;
    int cnt = (int) ans.size();
    for (auto i: ans) {
        string s1;
        while (i.size() < 4)i = ' ' + i;
        for (int j = 0; j < i.size(); j++) {
            if (i[j] == ' ')continue;
            if (i[j] == '0')s1 += i[j];
            else if (i[j] != '0') {
                s1 += i[j];
                if (j != i.size() - 1)s1 += mp[j];
            }
        }
        while (s1.back() == '0')s1.pop_back();
        if (s1.size()) {
            int ret = 0;
            for (int i = 0; s1[i] == '0' && i < s1.size(); i++)ret++;
            reverse(s1.begin(), s1.end());
            while (s1.back() == '0' && ret > 1) s1.pop_back(), ret--;
            reverse(s1.begin(), s1.end());
        }
        if (cnt == 3 && s1.size())s1 += 'Y';
        if (cnt == 2 && s1.size())s1 += 'W';
        cnt--;
        sans += s1;
    }
    //cout<<sans<<endl;
    for (int i = 0; i < sans.size() - 1; i++)if (sans[i] == '0' && sans[i + 1] == '0')sans[i] = '-';
    for (auto i: sans) {
        if (i == '-')continue;
        cout << i;
    }
    cout << endl;
}

/*10
0
10
102
70308432
12003
900000000000
100000000001
100000100001
10101010101
20001001001
 */

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

Problem H. 我爱XTU

这个题就是先把每个字母的前缀和求出来,然后用map来存它出现的次数,把前缀和相等的统计次数,他对答案的贡献就是n*(n-1)/2,如果是0,0就说明回到了最开始的时候,要把次数加上1,最后输出ans即可。

#include<bits/stdc++.h>

#define int long long
#define endl '\n'
#define fi first
#define se second

using namespace std;

const int N = 10010;

void solve() {
    string s;
    cin >> s;
    map<pair<int, int>, int> mp1;
    int sx[N]{}, st[N]{}, su[N]{};
    int x = 0, t = 0, u = 0;
    for (int i = 0; i < s.size(); i++) {
        if (s[i] == 'X')x++, sx[i] = x;
        else sx[i] = x;
        if (s[i] == 'T')t++, st[i] = t;
        else st[i] = t;
        if (s[i] == 'U')u++, su[i] = u;
        else su[i] = u;
    }
    int ans = 0;
    for (int i = 0; i < s.size(); i++)mp1[{sx[i] - st[i], sx[i] - su[i]}]++;
    for (auto &[a, b]: mp1) {
        if (a.fi == 0 && a.se == 0)b++;
        ans += b * (b - 1) / 2;
    }
    cout << ans << 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;
}