ICPC 2019 Central Russia(9/11)

ICPC Central Russia Regional Contest (CRRC 19)

A. Green tea

签到题

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
typedef long long LL;
int a, b;
int main() {
    cin >> a >> b;
    int res1, res2;
    int minn = 0x3f3f3f3f;
    for (int i = 0; i <= 1000; i++) {
        for (int j = 0; j <= 1000; j++) {
            if(i*a+j*b==80*(i+j)&&((i+j)!=0)){
                if(i+j<minn){
                    res1 = i, res2 = j;
                    minn = i + j;
                }
            }
        }
    }
    cout << res1 << ' ' << res2 << endl;
    return 0;
}

B. Mysterious Resistors

大意:

给出k组串联的电阻,每组电阻都是(r_i)和R并联,现在给出k个(r_i),以及总电阻,求R

思路:

因为有单调性,所以直接二分去找即可

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
int const MAXN = 2e5 + 10;
int n;
double m;
double r[MAXN];
bool check(double mid) {
    double sum = 0;
    for (int i = 1; i <= n; i++) {
        sum += r[i] / (1.0 + r[i] / mid);
    }
    return sum > m;
}
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> r[i];
    }
    double l = 0, r = 1e5;
    while (r - l > 1e-8) {
        double mid = (l + r) / 2;
        if (check(mid))
            r = mid;
        else
            l = mid;
    }
    printf("%.8lf
", l);
    return 0;
}

C. Emoticons

大模拟。

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
int const MAXN = 2e5 + 10;
int n, m, T;
map<char, int> num;
unordered_map<char, string> mp;
vector<char> f;
int main() {
    string s;
    cin >> s;
    mp['\'] = ":-\";
    f.push_back('\');
    mp['P'] = ":-P";
    f.push_back('P');
    mp['D'] = ":D";
    f.push_back('D');
    mp['C'] = ":C";
    f.push_back('C');
    mp['8'] = "8-0";
    f.push_back('8');
    mp['E'] = ":-E";
    f.push_back('E');
    mp['%'] = "%0";
    f.push_back('%');
    mp['X'] = ":-X";
    f.push_back('X');
    mp['~'] = ":~(";
    f.push_back('~');
    mp['['] = "[:|||:]";
    f.push_back('[');
    mp['0'] = ":-0";
    f.push_back('0');
    mp['|'] = ":-|";
    f.push_back('|');

    for (int i = 0; i < s.size(); i++) {
        num[s[i]]++;
        // cout << s[i] << endl;
    }
    for (int v = 0; v < f.size(); v++) {
        char fl = f[v];
        if (num[fl]) {
            string t = mp[fl];
            int d = num[fl];
            for (int i = 0; i < d; i++) {
                // cout << fl << " " << t << endl;
                cout << t << endl;
            }
            for (int i = 0; i < t.size(); i++) {
                num[t[i]] -= d;
            }
        }
    }
    if (num[';'] && num[')']) {
        int d = min(num[';'], num[')']);
        for (int i = 0; i < d; i++) {
            cout << ";-)" << endl;
        }
        num[';'] -= d;
        num['-'] -= d;
        num[')'] -= d;
    }
    if (num[';'] && num['(']) {
        int d = min(num[';'], num['(']);
        for (int i = 0; i < d; i++) {
            cout << ";-(" << endl;
        }
        num[';'] -= d;
        num['-'] -= d;
        num['('] -= d;
    }
    if (num[')']) {
        int d = num[')'];
        for (int i = 0; i < d; i++) {
            cout << ":)" << endl;
        }
        num[':'] -= d;
        num[')'] -= d;
    }
    if (num['(']) {
        int d = num['('];
        for (int i = 0; i < d; i++) {
            cout << ":(" << endl;
        }
        num[':'] -= d;
        num['('] -= d;
    }
    cout << "LOL" << endl;
    return 0;
}

D. Power play

大意:

给出两个数a和b,范围为1e4

现在要求求出一个1e18以内的数,使得(a^x==x^b)

思路:

1e18是个幌子,可以发现x不会超过1e4,所以直接暴力枚举即可

#include <bits/stdc++.h>

#define int long long
using namespace std;

inline int read() {
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}

int const MAXN = 2e5 + 10;
int n, m, T, a, b;

long double eps = 1e-8;

signed main() {
    a = read(), b = read();
    long double ai = a * 1.0, bi = b * 1.0;
    int flg = 0;
    for (int i = 1; i <= 1e6; ++i) {
        if (fabs(bi * log((long double)i) - (long double)i * log((long double)a)) < eps) {
            cout << i;
            flg = 1;
            break;
        }
    }
    if (!flg) cout << 0;
    return 0;
}

E. Printed circuit board

gugugu

F. A word game

sg函数裸题

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
typedef long long LL;
string s;
int a[30];
int f[100];
int sg(int x) {
    if (f[x] != -1) return f[x];
    unordered_set<int> S;
    if (x >= 1) S.insert(sg(x - 1));
    if (x >= 2) S.insert(sg(x - 2));
    if (x >= 3) S.insert(sg(0));
    for (int i = 0;; i++) {
        if (!S.count(i)) return f[x] = i;
    }
}

int main() {
    cin >> s;
    memset(f, -1, sizeof f);
    for (int i = 0; i < s.size(); i++) {
        a[s[i] - 'A']++;
    }
    int res = 0;
    f[0] = 0;
    for (int i = 0; i < 26; i++) {
        res ^= sg(a[i]);
    }
    if (res) cout << "Alice" << endl;
    else cout << "Bob" << endl;
    return 0;
}

G. Hourglass

gugugu

H. Men's showdown

集合nim游戏裸题

#include<bits/stdc++.h>

using namespace std;

int n, k;
int const N = 1e2 + 10, M = 1e4 + 10;
int s[N];
int f[M];

// 记忆化搜索求sg函数
int sg(int x) {
    if (f[x] != 0) return f[x];
    unordered_set<int> S; 
    
    // 计算每个后继状态的sg值
    for (int i = 1; i <= 3; ++i) {
        int sum = s[i];
        if (x >= sum) S.insert(sg(x - sum));
    }

    // mex运算
    for (int i = 0; ; i++)
        if (!S.count(i)) return f[x] = i;
}

int main() {
    // 读入集合s
    s[1] = 1, s[2] = 5, s[3] = 13;
    int x;
    cin >> x;
    int res = sg(x);
    if (!res) cout << "1
";
    else cout << "2
";
    return 0;
}

I. Andrew and Python

思路:

交互题,给出一个n*n的棋盘,然后有一个目标点,现在可以进行3种操作:

一种是询问目标点是否是某一个点

一种是询问目标点是否在某一条线段上

一种是询问目标点是否在某一个三角形上及内部

思路:

利用三角形询问进行二分,每次询问一半的三角形,到后面如果无法组成三角形,那么就利用线段进行二分

最后可能会剩下1-3个点,直接暴力询问即可

#include <bits/stdc++.h>

#define int long long
using namespace std;
typedef pair<int, int> PII;

inline int read() {
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}

int const MAXN = 2e5 + 10;
int n, m, T;

PII get_mid(PII x, PII y, PII z) {
    double res_x = (1.0 * x.first + 1.0 * y.first) / 2.0;
    double res_y = (1.0 * x.second + 1.0 * y.second) / 2.0;
    if (z.first < res_x)
        res_x = ceil(res_x);
    else
        res_x = floor(res_x);
    if (z.second < res_y)
        res_y = ceil(res_y);
    else
        res_y = floor(res_y);
    return {(int)res_x, (int)res_y};
}

int test(PII a, PII b, PII c) {
    if ((c.second - b.second) * (b.first - a.first) ==
        (b.second - a.second) * (c.first - b.first))
        return 1;
    else
        return 0;
}

int check(PII a, PII b, PII c) {
    if (!test(a, b, c)) {
        cout << "? 3 " << a.first << " " << a.second << " " << b.first << " "
             << b.second << " " << c.first << " " << c.second << endl;
        fflush(stdout);
        string s;
        cin >> s;
        if (s == "Yes")
            return 1;
        else
            return 0;
    } else {
        if (a == b) {
            return 0;
        } else {
            cout << "? 2 " << a.first << " " << a.second << " " << b.first
                 << " " << b.second << endl;
            fflush(stdout);
            string s;
            cin >> s;
            if (s == "Yes")
                return 1;
            else
                return 0;
        }
    }
}

int check2(PII a, PII b, PII c) {
    int ab = (a.first - b.first) * (a.first - b.first) +
             (a.second - b.second) * (a.second - b.second);
    int bc = (b.first - c.first) * (b.first - c.first) +
             (b.second - c.second) * (b.second - c.second);
    int ac = (a.first - c.first) * (a.first - c.first) +
             (a.second - c.second) * (a.second - c.second);
    if (ab < 4 && bc < 4 && ac < 4) return 0;
    return 1;
}

int Query(PII x) {
    cout << "? 1 " << x.first << " " << x.second << endl;
    fflush(stdout);
    string s;
    cin >> s;
    if (s == "Yes")
        return 1;
    else
        return 0;
}

void print(PII x) {
    cout << "! " << x.first << " " << x.second << endl;
    fflush(stdout);
}

signed main() {
    cin >> n;
    PII a, b, c;
    c = {1, 1}, a = {1, n}, b = {n, 1};
    if (!check(a, b, c)) c = {n, n};
    while (check2(a, b, c)) {
        PII mid = get_mid(a, b, c);
        if (check(a, c, mid)) {
            b = c, c = mid;
        } else {
            a = b, b = c, c = mid;
        }
    }
    if (Query(a)) {
        print(a);
    } else if (Query(b)) {
        print(b);
    } else if (Query(c)) {
        print(c);
    }
    return 0;
}

J. Something that resembles Waring's problem

大意:

给出一个数x,要求将其表示为不超过5个数的立方和的形式,x范围为1e100000

思路:

过于精妙....

来自:https://www.cnblogs.com/hyheng/p/14264678.html

图片.png

python3写了一发没过 ,应该是科学计数法导致的精度丢失,长了个教训,高精度就用Python2

n = input()
n = int(n)
r = n % 6
r3 = r * r * r
print('5')
print('%d %d %d %d %d' %(r, ((n - r3) / 6 + 1), ((n - r3) / 6 - 1), (-(n - r3) / 6), (-(n - r3) / 6)))

K. Parabolic sorting

大意:

给出n个不相等的数,要求将其排列为前降后升的序列,每次操作可以将相邻的两个点交换,问最小多少次交换可以完成

思路:

对于每个点,考虑将其放到前面下降的区间还是后面上升的区间

如果放到前面区间,那么需要操作的就是前面比他小的数的个数

如果放到后面区间,那么需要操作的就是后面比他小的个数

所以每个点算一下前面后面的个数,取min,最后相加即可

可以用树状数组,线段树来维护

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
int const N = 5e5 + 10;
LL c[N], n, a[N], l[N], r[N];
vector<LL> v;
unordered_map<LL, int> H;

int lowbit(int x) { return x & -x; }

void add(int x, int y) {
    for (int i = x; i <= n; i += lowbit(i)) c[i] += y;
}

LL query(int x) {
    LL res = 0;
    for (int i = x; i; i -= lowbit(i)) res += c[i];
    return res;
}

int main() {
    scanf("%lld", &n);
    memset(c, 0, sizeof c);
    v.clear();
    H.clear();
    for (int i = 1; i <= n; ++i) {
        scanf("%lld", &a[i]);
        v.push_back(a[i]);
    }
    sort(v.begin(), v.end());
    int cnt = 1;
    for (int i = 0; i < v.size(); ++i) H[v[i]] = cnt++;  // 离散化
    LL res = 0;
    for (int i = n; i >= 1; --i) {  // 计算每个H[a[i]]出现的次数
        r[i] = query(H[a[i]] - 1);  // 加上H[a[i]-1]出现的总次数
        add(H[a[i]], 1);            // 次数加一
    }
    for (int i = n; i >= 1; --i) {
        add(H[a[i]], -1);
    }
    for (int i = 1; i <= n; ++i) {  // 计算每个H[a[i]]出现的次数
        l[i] = query(H[a[i]] - 1);  // 加上H[a[i]-1]出现的总次数
        add(H[a[i]], 1);            // 次数加一
    }
    for (int i = 1; i <= n; ++i) {
        res += min(r[i], l[i]);
    }
    cout << res << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14461552.html