ICPC2020上海站 补题

本文解析了四个算法题目,包括Fibonacci数列求和、文件目录删除模拟、扫雷游戏策略调整及二人行走最优路径寻找。文章通过具体代码展示了如何使用C++解决这些问题,并分享了解题思路和优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

(未完待续)

### ICPC 上海区域赛中文信息及相关详情 #### 比赛简介 国际大学生程序设计竞赛(International Collegiate Programming Contest, ICPC)是一项全球性的编程比赛,旨在通过解决复杂的算法问题来评估学生的逻辑思维能力和团队协作精神。ICPC上海区域赛是中国赛区的重要组成部分之一。 #### 历史回顾与经验分享 在过去几年中,ICPC上海区域赛吸引了众多高校参与。例如,在2019年的比赛中,有参赛者提到该赛事不仅是一次技术上的挑战,同时也提供了良好的交流机会[^3]。而在2020年的比赛中,则出现了因细节错误而导致的罚时情况,这提醒选手们在比赛中需格外注意代码质量以及测试用例覆盖范围[^4]。 #### 时间安排 具体的时间表会每年有所调整,但通常情况下,ICPC上海区域赛会在秋季举行。根据最近两年的日程来看,预计未来几年的比赛时间仍将在这一时间段内展开[^1]。确切日期一般由官方提前数月公布于其网站上,请定期访问相关链接获取最新动态。 #### 地点设置 比赛场地设在上海某所大学校园内部或者周边会议中心等地。实际位置取决于当年主办方的选择,并且可能会随着合作院校的变化而改变。因此建议关注ICPC北京总部及本地分部发布的公告以获得最精确的信息[^1]。 #### 参赛资格与队伍构成 任何全日制在校本科生均有资格报名参加此项活动;每支代表队限三人组成,成员之间应具备良好沟通技巧并能高效分工完成任务目标。需要注意的是,部分特殊规则可能涉及往届成绩考量等因素,所以务必仔细阅读当年度指南说明文件后再做决定是否组建新团队或是沿用旧阵容继续冲击更高荣誉等级[^2]。 ```python # 示例:如何查询最新的ICPC上海站信息? import requests def fetch_icpc_shanghai_info(): url = "https://icpc.baylor.edu/" # 替换为具体的上海站点URL response = requests.get(url) if response.status_code == 200: print("成功获取ICPC上海区域赛信息") return response.text[:50] + "..." # 返回前50字符作为示例展示 else: raise Exception(f"无法连接至服务器,状态码:{response.status_code}") fetch_icpc_shanghai_info() ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值