2017 ECNA Regional Contest

2017 ECNA Regional Contest

A

B

C

模拟

int main() {
    IOS; string s; cin >> s;
    int x = 0, y = 0;
    rep(i, 0, s.size() - 2 >> 1) x += s[i] - 'A', y += s[i + (s.size() >> 1)] - 'A';
    rep(i, 0, s.size() - 2 >> 1) s[i] = ((s[i] - 'A') + x + (s[i + (s.size() >> 1)] - 'A') + y) % 26 + 'A';
    rep(i, 0, s.size() - 2 >> 1) cout << s[i];
    return 0;
}

D

栈模拟

int main() {
    IOS; string s; cin >> n >> m; stack<int> st;
    rep(i, 1, m) {
        cin >> s; int x = 0;
        if (isdigit(s[0]) || s[0] == '-') {
            rep(i, s[0] == '-', s.size() - 1) x = x * 10 + s[i] - '0';
            if (s[0] == '-') x = -x;
            st.push(k); k = ((k + x) % n + n) % n;
        } else {
            cin >> x;
            while (x > 0 && !st.empty()) k = st.top(), st.pop(), --x;
        }
    }
    cout << k;
    return 0;
}

E

考察弗洛伊德和离散化

unordered_map<string, int> st;
bool d[N][N], h[N][N];
 
int getid(string& s) {
    return st.count(s) ? st[s] : st[s] = st.size() + 1;
}
 
int main() {
    IOS; cin >> n >> m;
    rep (i, 1, n) {
        string s, op, t; cin >> s >> op >> t;
        int x = getid(s), y = getid(t);
        if (op[0] == 'i') d[x][y] = 1;
        else h[x][y] = 1;
    } n = st.size();
    rep (i, 1, n) d[i][i] = 1;
    rep (k, 1, n) rep (i, 1, n) rep (j, 1, n) if (d[i][k] & d[k][j]) d[i][j] = 1;
    rep (k, 1, n) rep (i, 1, n) rep (j, 1, n)
        if ((d[i][k] & h[k][j]) | (h[i][k] & d[k][j]) | (h[i][k] & h[k][j])) h[i][j] = 1;
    rep (i, 1, m) {
        string s, op, t; cin >> s >> op >> t;
        cout << "Query " << i << ": ";
        int x = getid(s), y = getid(t);
        if (max(x, y) > n) cout << "false\n";
        else if (op[0] == 'i') cout << (d[x][y] ? "true\n" : "false\n");
        else cout << (h[x][y] ? "true\n" : "false\n");
    } 
    return 0;
}

F

一开始写成了重心, 然而并不是

重心是均分分支, 而这道题是找到某个点使得分裂后 对数最多, 那直接枚举每个点就好了

VI h[N];
int sz[N];
ll n1, mxa, mxb;
 
void dfs(int x, int fa) {
    sz[x] = 1; VI a; ll cur = 0, s = 0, mx1 = 0, mx2 = 0;
    for (auto y : h[x]) if (y != fa) dfs(y, x), sz[x] += sz[y], a.pb(sz[y]);
    a.pb(n + 1 - sz[x]);
    for (auto i : a) {
        cur += i * s, s += i;
        if (mx1 < i) mx2 = mx1, mx1 = i;
        else umax(mx2, i);
    }
    if (umax(n1, cur)) mxa = mx1, mxb = mx2;
}
 
int main() {
    IOS; cin >> n;
    rep (i, 1, n) {
        int u, v; cin >> u >> v;
        h[u].pb(v); h[v].pb(u);
    }
    dfs(0, -1);
    cout << n1 << ' ' << n1 - mxa * mxb;
    return 0;
}

G

n很小, 又没到爆搜的地步, 那就朴素的线性dp

f[i][j] 表示在第 i 天能吃 \(m*(2/3)^j\) 热量的情况下最多能吃多少

要么连续吃(第 i + 1 天也吃)则 f[i + 1][j + 1] = max(f[i + 1][j + 1], f[i][j] + min(m, a[i + 1]))

要么隔天吃(第 i + 1 天不吃, i + 2 天吃)则 f[i + 2][j] = max(f[i + 2][j], f[i][j] + min(m, a[i + 2]))

或者连续两天不进食, f[i + 3][0] = max(f[i + 3][0], f[i][j] + max(m, a[i + 3]))

注意到 f[i][0] = max(m, a[i])

ll f[N][N], a[N], d[N];
 
int main() {
    IOS; cin >> n >> m; d[0] = m;
    rep (i, 1, n) cin >> a[i], d[i] = d[i - 1] * 2 / 3, f[i][0] = min((ll)m, a[i]);
    rep (i, 1, n) rep (j, 0, n) {
        rep (k, 1, min(n - i, 2)) umax(f[i + k][j + 2 - k], f[i][j] + min(d[j + 2 - k], a[i + k]));
        umax(f[i + 3][0], f[i][j] + min(a[i + 3], (ll)m));
    }
    cout << *max_element(f[n], f[n] + n + 1);
    return 0;
}

H

怎么找都行, 爆搜完事

int d[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}};
char a[N][N];
 
void dfs(int x, int y) {
    a[x][y] = '.';
    rep (i, 0, 7) {
        int dx = x + d[i][0], dy = y + d[i][1];
        if (a[dx][dy] != '#') continue;
        dfs(dx, dy); 
    }
}
 
int main() {
    IOS; cin >> n >> m; rep (i, 1, n) cin >> a[i] + 1;
    rep (i, 1, n) rep (j, 1, m) if (a[i][j] == '#') dfs(i, j), ++k;
    cout << k;
    return 0;
}

I

暴力拼接算式, 再计算

首先要添加括号, 意味着 优先级高的符号链接的前面的数 要和 后面通过低级运算算出的数 运算

一共就3个运算符, 那么最多存在() 或 ()() 不存在 (()), (()) 必定可以拆掉一个括号

d / (a * (b - c)) = d / a * (b - c)

所以我们怎么拼接算是呢?

将要填一个数, 那么可以在前面添加一个 '(' 在添加要添加的 运算数, 然后可以添加一个 ')', 再添加运算符 +-*/, 注意括号的匹配, 且不能连续添加括号[不存在(())]

最后运算中缀串就好了, 去合法的最小代价

stack<int> nums;
stack<char> ops;
bool flag = 1;

void cal() {
    int a = nums.top(); nums.pop();
    int b = nums.top(); nums.pop();
    char c = ops.top(); ops.pop();
    switch (c) {
    case '+': nums.push(b + a); break;
    case '-': nums.push(b - a); break;
    case '*': nums.push(b * a); break;
    case '/': if (a) flag = flag & (b % a == 0), nums.push(b / a);
            else flag = 0, nums.push(2); break;
    }
}

void read(int& i, string& s) {
    int t = 0;
    for (; isdigit(s[i]); ++i) t = t * 10 + s[i] - '0';
    nums.push(t); --i;
}

int ask(string s) {
    while (!nums.empty()) nums.pop();
    while (!ops.empty()) ops.pop(); flag = 1;
    s = '(' + s + ')';
    for (int i = 0; i < s.size(); ++i)
        if (isdigit(s[i])) read(i, s);
        else
            switch (s[i]) {
            case '(': ops.push('('); break;
            case '+': case '-': while (ops.top() != '(') cal(); ops.push(s[i]); break;
            case '*': case '/': while (ops.top() == '*' || ops.top() == '/') cal(); ops.push(s[i]); break;
            case ')': while (!ops.empty() && ops.top() != '(') cal(); ops.pop(); break;
            }
    return nums.top();
}

int n, m, _, k, a[4], b[4], c[4], x, y;
bool v[4];
string s;

int get() {
    memcpy(c, b, sizeof b); int ans = 0;
    per(i, 3, 1) if (c[i] != a[i]) {
        int k = 0;
        rep(j, 0, i - 1) if (c[j] == a[i]) k = j;
        rep(j, k, i - 1) swap(c[j], c[j + 1]), ++ans;
    }
    return ans;
}

int write(string& s, int k) {
    string t; while (k) t += k % 10 + '0', k /= 10;
    reverse(all(t));  s += t;
}

void addop(string& s, int cur, void(*dfs)(int)) {
    s += '+'; dfs(cur + 1); s.back() = '-'; dfs(cur + 1);
    s.back() = '*'; dfs(cur + 1); s.back() = '/'; dfs(cur + 1);
    s.pop_back();
}

void dfs(int cur) {
    if (cur == 4) {
        if (x != y) return; s.pop_back();
        if (ask(s) == 24 && flag) umin(m, x + get() * 2);
        s += '*'; return;
    }
    if (x == y) {
        s += '('; ++x; int len = s.size();
        rep(i, 0, 3) if (!v[i]) {
            v[i] = 1; write(s, b[cur] = a[i]);
            addop(s, cur, dfs);  v[i] = 0;
            while (s.size() != len) s.pop_back();
        }
        s.pop_back(); --x;
    }
    int len = s.size();
    rep(i, 0, 3) if (!v[i]) {
        v[i] = 1; write(s, b[cur] = a[i]);
        if (x > y) { ++y; s += ')'; addop(s, cur, dfs); s.pop_back(); --y; }
        addop(s, cur, dfs); v[i] = 0;
        while (s.size() != len) s.pop_back();
    }
}

int main() {
    IOS; cin >> a[0] >> a[1] >> a[2] >> a[3]; m = 2e9; dfs(0);
    if (m == 2e9) cout << "impossible";
    else cout << m;
    return 0;
}

J

模拟

int a[N], b[N], u[N], r[N], t[N], s;
 
int main() {
    IOS; rep (i, 0, 9) cin >> a[i] >> b[i];
    rep (i, 0, 9) cin >> u[i] >> r[i] >> t[i];
    rep (i, 0, 29) {
        if (s >= t[i % 10]) {
            int d = s - t[i % 10];
            int k = d / (u[i % 10] + r[i % 10]) * (u[i % 10] + r[i % 10]);
            t[i % 10] += (k + u[i % 10]); umax(s, t[i % 10]);
            t[i % 10] += r[i % 10];
        }
        s += a[i % 10]; umax(t[i % 10], s); s += b[i % 10];
    }
    cout << s - b[9] << endl;
}

K

这题是训练的时候随便加的一道题

01分数规划, 二分就行

struct node{ int x, y, z; };
int n, v[N];
vector<node> ve;
double ans, e[N][N], dis[N];

void prim(double x) {
    rep (i, 1, n) {
        double mi = 2e9; int now;
        rep (j, 0, n - 1) if(!v[j] && dis[j] < mi) mi = dis[j], now = j;
        v[now] = 1; ans += dis[now];
        rep (j, 0, n - 1) dis[j] = min(dis[j], abs(ve[now].z - ve[j].z + 0.0) - x * e[now][j]);
    }

}

bool judge(double x) {
    rep (i, 0, n - 1) dis[i] = 2e9, v[i] = 0;
    dis[0] = 0; ans = 0; prim(x);
    return ans > 0;
}

int main() {
    while (read(n), n) {
        vector<node>().swap(ve);
        for (int i = 1, x, y, z; i <= n; ++i) {
            cin >> x >> y >> z; 
            ve.pb(node{x, y, z});
        }                      
        rep (i, 0, n - 1) rep (j, 0, n - 1)
            e[i][j] = sqrt(0.0 + sqr(ve[i].x - ve[j].x) + sqr(ve[i].y - ve[j].y));
        double l = 0, r = 2e9;
        while(r - l > eps) {
            double mid = (l + r) / 2;
            if (judge(mid)) l = mid;
            else r = mid;
        }
        printf("%0.3f\n", r);
    }
    return 0;
}
posted @ 2021-01-23 18:48  洛绫璃  阅读(81)  评论(0编辑  收藏  举报