3.21校赛

本文通过分析多个编程竞赛题目,探讨了题意理解、算法应用与优化、读题技巧、持久化思考以及团队协作等方面的重要性。作者指出,正确理解题目、熟练运用动态规划、图论等算法、加强读题能力和后期持久思考是提高竞赛表现的关键。同时,团队间的有效沟通和规律性训练能提升解题效率和质量。
摘要由CSDN通过智能技术生成

3.21校赛

A题目

题意

给出字符串,以标点符号为界,写成一个大写一个小写的形式

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 100003;
const int MAX = 1e3 + 10;
 
int main() {
    string str;
    cin >> str;
    int len = str.length();
    int cnt = 0;
    for(int i = 0; i < len; i++) {
        if(!isalpha(str[i])) {
            cnt = 0;
            printf("%c", str[i]);
        }
        else {
            cnt++;
            if(cnt % 2) printf("%c", toupper(str[i]));
            else printf("%c", tolower(str[i]));
        }
    }
}

H题目

题意

给n,S,(1 <= n <= 1000, 0 <= S <= 3000)问又多少中分法,使得数组a大小为n(ai为非负数,且不递减,总和为S),取模,MOD = 998255353

题解

其实,对于n个数,我只要取出每个ai的个数,就好了,因为排序规定了,

即对于不同的n个数,对于答案贡献为1,

那么,就可以忽略 数组内部不递减,这个条件

那么,问题就等价于S个数,分为n组,有几种分法

这就是计数DP板子题

啊,举个例子,S = 15, n = 5

1 2 3 4 5 和 5 4 3 2 1 是一样的(或者可以认为后面的忽略掉了

1 2 2 5 5 是不一样的

那只要考虑取出的数是不一样的排列,ans++

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 998244353;
const int MAX = 5e3 + 10;
int dp[MAX][MAX];

int main() {
    int n, V;
    scanf("%d%d", &n, &V);
    for(int i = 1; i <= n; i++) dp[i][0] = 1;
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= V; j++) {
            if(j >= i) dp[i][j] = (dp[i - 1][j] + dp[i][j - i]) % MOD;
            else dp[i][j] = dp[i - 1][j] % MOD;
        }
    }
    printf("%d\n", dp[n][V] % MOD);
}

I题目

题意

给出两个字符串s,t,以及每一秒变化的数数组a, b(变化是指每一秒ai对应的si字典序加ai,but保证为小写字母(‘z’下面又是’a’)),问q次询问(q<=1e6),变化t(t<=1e18),问每次变化的最长公共子序列多长,s,t字符串字长1e3

题解

其实很简单,因为我注意到了t一定是要mod26的,26次以后就是一个循环

那么只要预处理一下就好了

我应该坚定的,LCS复杂度O(n^2),那么就1e6了,不可能再*q次询问的(主要是我记得好像有LCSo(n)的解法,误导我自己了,就算是这样1e9也不一定过的了

不对,1e9是铁T

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MOD = 100003;
const int MAX = 1e3 + 10;
char s[MAX], t[MAX];
int dp[30][MAX][MAX];
int len1, len2;
int a[MAX], b[MAX];
char s1[MAX], t1[MAX];
void solve() {
    for(int k = 0; k < 26; k++) {
        for(int i = 1; i <= len1; i++) s1[i] = (char) ('a' + (s[i] - 'a' + k * a[i]) % 26);
        for(int i = 1; i <= len2; i++) t1[i] = (char) ('a' + (t[i] - 'a' + k * b[i]) % 26);
        for(int i = 1; i <= len1; i++) {
            for(int j = 1; j <= len2; j++) {
                if(s1[i] == t1[j]) dp[k][i][j] = dp[k][i - 1][j - 1] + 1;
                else dp[k][i][j] = max(dp[k][i - 1][j], dp[k][i][j - 1]);
            }
        }
    }
}

int main() {
    int n, m;
    scanf("%d%d\n", &n, &m);
    scanf("%s\n", s + 1);
    scanf("%s\n", t + 1);
    len1 = strlen(s + 1);
    len2 = strlen(t + 1);
    for(int i = 1; i <= len1; i++) scanf("%d", &a[i]);
    for(int i = 1; i <= len2; i++) scanf("%d", &b[i]);
    solve();
    ll q;
    scanf("%lld", &q);
    while(q--) {
        ll t;
        scanf("%lld", &t);
        printf("%d\n", dp[t % 26][len1][len2]);
    }
}

J题目

题意

一个开关,有p(p = n / 1e4)的概率打卡,可以操作无限次,问最大的概率是多少

题解

p >= 0.5 ==> ans = p;

p >= 0 && p < 0.5 ==> ans = 0.5;

p = 0 ==> ans = 0;

《大胆猜测,小心求证》

(可以打一下前几项的概率,输入不同的值,其实是满足猜测的,就试试

《打表找规律》

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 100003;
const int MAX = 1e3 + 10;

int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        double n;
        scanf("%lf", &n);
        double ans = 0;
        if(n == 0) ans = 0;
        else if(n >= 5000) ans = n / 10000;
        else ans = 0.5;
        printf("%.6lf\n", ans);
    }
}

C题目

题意

有n个人,每个人权重xi, 可以玩ai次,如果输了,就直接淘汰,如果两个人Pk,得到的权值li为xi ^ xj + xi + xj,问权值最大为多少

题解

可以将一个人分成两个点思考,对于i点所有可以击败的点j,连边流量为1,权值为xi ^ xj + xi + xj,源点S流向i点,如果i是最大的点,那么他可以赢ai次,流量为ai,否则一定会被打败一次,流量为ai - 1

对于点i来说,流入的代表可以赢的场次,能够流通的点,代表可以打败,上面还有费用权重,对于被打败的j点来说,流出的流量为1,代表输了一次就下场了

这样可以求最小费用流,问题是最大费用流,那么取反。

tips

我竟然不知道,^ 的 优先级 比 + 小(我还以为是一样的)

一 个 没 有 用 到 的 却 感 觉 比 较 有 用 的 知 识 点 : a + b = 2 ×   ( a & b ) + a   x o r   b ; \color{blue}一个没有用到的却感觉比较有用的知识点: a + b = 2 \times\ (a \& b) + a \ xor\ b; :a+b=2× (a&b)+a xor b;
a   x o r   b + a & b = a ∣ b \color{blue}a\ xor \ b + a \& b = a | b a xor b+a&b=ab

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAX = 2e6 + 10;
#define SZ(v) (int)v.size()
#define pii pair<ll,ll>

const ll INF = 0x3f3f3f3f;
const ll MAXN = 2e6 + 10;

struct MCMF {
    struct Edge {
        ll v, cap, cost, rev;
        Edge(ll v, ll cap, ll cost, ll rev):v(v),cap(cap),cost(cost),rev(rev){}
    };

    ll flow, cost, s, t, n;
    ll dist[MAXN], H[MAXN], pv[MAXN], pe[MAXN];
    std::vector<Edge> G[MAXN];

    bool dijkstra() {
        std::priority_queue<pii, std::vector<pii>, std::greater<pii> > q;
        std::fill(dist, dist + n + 1, INF);
        dist[s] = 0; q.push({0, s});
        while (!q.empty()) {
            pii x = q.top(); q.pop();
            ll &u = x.second;
            if (dist[u] < x.first) continue;
            for (int i = 0; i < SZ(G[u]); ++i) {
                Edge &e = G[u][i];
                ll &v = e.v;
                pii y(dist[u] + e.cost + H[u] - H[v], v);
                if (e.cap > 0 && dist[v] > y.first) {
                    dist[v] = y.first;
                    pe[v] = i, pv[v] = u;
                    q.push(y);
                }
            }
        }

        if (dist[t] == INF) return false;
        for (int i = 0; i <= n; ++i) H[i] += dist[i];

        ll f = INF;
        for (int v = t; v != s; v = pv[v]) f = std::min(f, G[pv[v]][pe[v]].cap);

        flow += f;
        cost += f * H[t];

        for (int v = t; v != s; v = pv[v]) {
            Edge &e = G[pv[v]][pe[v]];
            e.cap -= f;
            G[v][e.rev].cap += f;
        }

        return true;
    }

    void solve(int s, int t) {
        this->s = s, this->t = t;
        flow = cost = 0;
        std::fill(H, H + n + 1, 0);
        while (dijkstra());
    }

    void init(int n) {
        this->n = n;
        for (int i = 0; i <= n; ++i) G[i].clear();
    }

    void add_edge(ll u, ll v, ll cap, ll cost) {
        G[u].push_back(Edge(v, cap, cost, SZ(G[v])));
        G[v].push_back(Edge(u, 0, -cost, SZ(G[u]) - 1));
    }

} mcmf;
ll x[MAX];
ll a[MAX];

int main() {
    ll n;
    scanf("%lld", &n);
    ll s = 2 * n + 1, t = s + 1;
    mcmf.init(t);
    int posmax = 0;
    ll maxx = -1;
    for(int i = 0; i < n; i++) {
        scanf("%lld%lld", &x[i], &a[i]);
        if (x[i] > maxx) {
            maxx = x[i];
            posmax = i;
        }
        mcmf.add_edge(s, i, a[i] - 1, 0);
        mcmf.add_edge(i + n, t, 1, 0);
    }
    mcmf.add_edge(s, posmax, 1, 0);
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(x[i] > x[j]) {
                ll cost = (x[i] ^ x[j])  + (x[i] + x[j]);
                //ll cost = (x[i] | x[j]) * 2;
                mcmf.add_edge(i, j + n, 1, -cost);
            }
        }
    }
    mcmf.solve(s, t);
    ll ans = mcmf.cost;
    printf("%lld\n", -ans);
}

个人总结

我发现了我的舒适点, 还有薄弱点( 这周发现的)
即绕好几个弯的思维题( 优化题面, 简化问题) , ( 校赛证明DP 我还是可以出的嘛
我的缺点是读题太差( 且不是很愿意读题, 开新的题目, 在后两个小时最为明显)
后劲不足, 两小时后就不去思考了
图论这块差( 按照知识点来说

团队总结

( 校赛第七名, 除去打星

总的来说, 比较幸运。

( 我们前6 题, 只PE 了一次( 十分可惜, 如果正式比赛有热身赛, 就可以试错规避) , 罚时较少

后面出了G 题, 属于较难题目, 且比赛后半段思维感觉不是很活跃

优点是罚时少, 简单题目出题比较稳且快

缺点是, 确实能力有限, 难题不会写, 较高强度思考使得脑子太快糊掉了( 要多进行长时间的训练

经验:

不一定要跟榜, 可以先随意开, 有思路就试一试, 就比如说开了H 题, 果断试了一下, 过了( 感觉信心也+ + 了

注重cin cout 的关闭同步流, 不能因为这个T , 造成罚时

交流大声一点, 确保队友有效交流

对于不确定的题目( 指的是不能严格证明, but 大致推测除了规律的题目) , 和队友交流一下, 感觉没有问题, 就冲

善用打表看规律( 适于是在出不了题目的情况), 其实E 题会发现3 * c * c 无解, 2 * c * c 解是c * c 的解法+ 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的公寓报修管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本公寓报修管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此公寓报修管理系统利用当下成熟完善的Spring Boot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。公寓报修管理系统有管理员,住户,维修人员。管理员可以管理住户信息和维修人员信息,可以审核维修人员的请假信息,住户可以申请维修,可以对维修结果评价,维修人员负责住户提交的维修信息,也可以请假。公寓报修管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:公寓报修管理系统;Spring Boot框架;MySQL;自动化;VUE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值