ICPC2020上海站 补题

G. Fibonacci

签到题,总感觉推了一个非常笨重的公式。。。
当然, 1e9 日常爆int,要用 long long

#include <bits/stdc++.h>

#define int long long
using namespace std;

signed main() {
    int n, sum = 0;
    cin >> n;
    sum += (n % 3 * 2 + (n / 3 - 1) * 3) * (n / 3) / 2;
    if (n % 3) sum += (1 + (n - n % 3) / 3) * (n - n % 3) / 3;
    else sum += (1 + n / 3) * n / 3;
    cout << sum;
    return 0;
}

M. Gitignore

一道模拟题,利用 map 的有序,将每一段文件地址的前缀目录导入 map ,被保护则 value = 0 ,需删除则 value = 1 ,同时当删除一个目录后,这个目录的子目录无需再次执行删除,子目录的检测采用字符串切割与字符 / 在目录中出现次数作为判定依据,这种写法的好处是无需考虑不同目录级数下的同名文件。
思考过程中被卡了一段时间,卡的原因就是只用字符串切割判断,而没有判断目录级数,卡住的自造测试数据与输出如下:

1
3 1
aa/bb
aa/bbb
aa/bbbb
aa

程序输出为(带 ** 的是调试数据,即 map 的元素顺序输出,在程序中已注释掉):

**aa 0
**aa/bb 1
**aa/bbb 1
**aa/bbbb 1
1

下面是满分代码:

#include <bits/stdc++.h>

#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(x, y, z) for(int (x)=(y);(x)<=(z);++(x))
#define psi pair<string,int>
#define int long long

using namespace std;
int T = 1;
map<string, int> mp;

void solve() {
    int n, m;
    string a;
    mp.clear();
    cin >> n >> m;
    rep(i, 1, n) {
        cin >> a;
        cin.sync();
        mp.insert((psi) {a, 1});
        string tmp;
        rep(j, 0, a.length() - 1) {
            if (a[j] == '/') {
                tmp = a.substr(0, j);
                mp.insert((psi) {tmp, 1});
                tmp.clear();
            }
        }
    }
    rep(i, 1, m) {
        cin >> a;
        cin.sync();
        string tmp;
        mp[a] = 0;
        rep(j, 0, a.length() - 1) {
            if (a[j] == '/') {
                tmp = a.substr(0, j);
                mp[tmp] = 0;
                tmp.clear();
            }
        }
    }
    int res = 0;
    string ck;
    for (psi p : mp) {
        // cout<<"**"<<p.first<<" "<<p.second<<'\n';
        if (p.second == 1) {
            string next_str = p.first.substr(0, ck.length());
            if (ck.length() && next_str == ck &&
                count(p.first.begin(), p.first.end(), '/') != count(ck.begin(), ck.end(), '/'))
                continue; //上层目录已经被删除,无需重复删除
            ++res;
            ck = p.first;
        }
    }
    cout << res << '\n';
}

signed main() {
    start;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

B. Mine Sweeper II

vice versa为拉丁文,意为“反之亦然”

扫雷游戏,题面概括一下就是将没有雷的格子四周八个格的地雷数量作为这个 non-mine cell 的值,通过对B图最多(m*n)/2次数的修改,让两图 non-mine cell 值的总和相等。实际上只需要数一下B改成A所需修改次数,若小于等于 (m*n)/2 ,则直接输出A图,否则输出取反的A图( m*n 减去一个大于 (m*n)/2 的数,差值必然小于(m*n)/2,也就是 no solution exists 输出-1的情况是不存在的)。

#include <bits/stdc++.h>

#define rep(x, y, z) for(int x=y;x<=z;x++)

using namespace std;
int a[1001][1001], b[1001][1001];

int main() {
    int n, m, cnt = 0, flag = 0;
    char c;
    cin >> n >> m;
    rep(i, 1, n) {
        rep(j, 1, m) {
            cin >> c;
            a[i][j] = c == '.' ? 0 : 1;
        }
    }
    rep(i, 1, n) {
        rep(j, 1, m) {
            cin >> c;
            b[i][j] = c == '.' ? 0 : 1;
            cnt += a[i][j] == b[i][j] ? 0 : 1;
        }
    }
    if (cnt > (n * m) / 2) flag = 1;
    rep(i, 1, n) {
        rep(j, 1, m) cout << ((flag - a[i][j] == 0) ? '.' : 'X');
        cout << '\n';
    }
    return 0;
}

D. Walker

可以分三种情况讨论:

  1. 其中一人走完全程(一人速度远大于另一人时该方案用时最短)
  2. 两人相向而行
  3. 在p1到p2找到一点 mid ,使 mid 左右两端路程分别由两人自己走完,通过二分法多次选取 mid 点,尽可能使两人所用时间相等

虽然题目要求与答案之间的差值不大于 1e6 ,但实际上采用精确度作为二分循环的条件会超时,这里 cnt = 32 是一个能通过牛客和CF上这道题的数据评测的最小值,实际上就算改成 200 也不会超时。

#include <bits/stdc++.h>

#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;
int T = 1;
// const double esp = 1e-7;

double go(double nn, double p, double v) {
    double res = (min(p, nn - p) + nn) / v;
    return res;
}

int main() {
    start;
    cin >> T;
    while (T--) {
        double n, p1, v1, p2, v2;
        cin >> n >> p1 >> v1 >> p2 >> v2;
        if (p1 > p2) {
            swap(p1, p2);
            swap(v1, v2);
        }
        double ans1 = min(go(n, p1, v1), go(n, p2, v2));
        double ans2 = max((n - p1) / v1, p2 / v2);
        double l = p1, r = p2, t1, t2, mid;
        int cnt = 32;
        do {
            mid = (l + r) / 2.0;
            t1 = go(mid, p1, v1);
            t2 = go(n - mid, n - p2, v2);
            if (t1 > t2) r = mid;
            else l = mid;
        } while (--cnt);//abs(t1 - t2) > esp
        double ans3 = max(t1, t2);
        cout << fixed << setprecision(10) << min(min(ans1, ans2), ans3) << '\n';
    }
    return 0;
}

I. Sky Garden

(未完待续)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值