AtCoder Regular Contest 99

本文精选了算法竞赛中的几道经典题目,包括最小化问题、Snuke数、独立集划分、符号吃掉问题,详细解析了每道题目的解题思路与代码实现,涵盖了贪心算法、规律寻找、图论与哈希技巧。
Seed-Coder-8B-Base

Seed-Coder是一个功能强大、透明、参数高效的 8B 级开源代码模型系列,包括基础变体、指导变体和推理变体,由字节团队开源

传送门

C - Minimization

第一次可能有多种选择,我们枚举所有的选择,然后两边贪心取即可。

Code

#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
//#define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5;

int n, k;

void run() {
    int p;
    for(int i = 1; i <= n; i++) {
        int x; cin >> x;
        if(x == 1) p = i;
    }
    int ans = N;
    for(int i = 1; i <= n; i++) {
        int l = i, r = min(n, i + k - 1);
        if(l <= p && p <= r)
            ans = min(ans, 1 + (l - 1 + k - 2) / (k - 1) + (n - r + k - 2) / (k - 1));
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
#ifdef Local
    freopen("../input.in", "r", stdin);
    freopen("../output.out", "w", stdout);
#endif
    while(cin >> n >> k) run();
    return 0;
}

D - Snuke Numbers

这个就是打表找规律...但规律也不是很好找,这个规律是变换的规律,可能一次加上\(10^i\),也可以加上\(10^{i+1}\),两个判断一下即可。

Code

#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5;

int K;

double Snuke(ll x) {
    ll tmp = 0, c = x;
    while(c) {
        tmp += c % 10;
        c /= 10;
    }
    return 1.0 * x / tmp;
}

void run() {
    ll res = 0, x = 1;
    while(K--) {
        double t1, t2;
        while(true) {
            t1 = Snuke(res + x), t2 = Snuke(res + x * 10);
            if(t1 <= t2) break;
            x *= 10;
        }
        res += x;
        cout << res << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
#ifdef Local
    freopen("../input.in", "r", stdin);
    freopen("../output.out", "w", stdout);
#endif
    while(cin >> K) run();
    return 0;
}

E - Independence

题意:
给出\(n\)个点\(m\)条无向边,现在对于任意两个点,至多有一条边直接连接。
现在要将这个图划分为两部分,使得两部分都为完全图,问最终每部分最小边数之和为多少。

思路:

  • 划分为两部分之后的答案很好计算,假设两边的点分别有\(x,y\)个,那么最终答案就为\(\frac{x\cdot (x-1)}{2}+\frac{y\cdot (y-1)}{2}\)
  • 现在就考虑如何划分。
  • 我们取原图的补图,那么最终两个集合中不存在任何一条边即符合条件。
  • 进一步地,我们将这个与二分图等价,其实就将问题转化为二分图问题了。
  • 首先判断二分图是否存在,若存在,先有若干个连通块,每个连通块有两种选择,那么直接背包\(dp\)一下求出最终所有方案数就行了。

(一开始还以为能够滚动一维QAQ)
代码如下:

Code

#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
//#define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 705;
 
int n, m;
bool lnk[N][N];
int cnt[2];
int col[N];
bool f;
 
void dfs(int u, int c) {
    col[u] = c;
    ++cnt[c];
    for(int v = 1; v <= n; v++) {
        if(lnk[u][v]) {
            if(col[v] == -1) dfs(v, 1 - c);
            else if(col[v] == c) {
                f = false;
                return;
            }
        }
    }
}
 
pii num[N];
bool dp[N][N];
 
void run() {
    memset(col, -1, sizeof(col));
    memset(dp, 0, sizeof(dp));
    f = true;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++) {
            if(i != j) lnk[i][j] = 1;
        }
    for(int i = 1; i <= m; i++) {
        int u, v; cin >> u >> v;
        lnk[u][v] = lnk[v][u] = 0;
    }
    int tot = 0;
    for(int i = 1; i <= n; i++) {
        if(col[i] == -1) {
            cnt[0] = cnt[1] = 0;
            dfs(i, 0);
            num[++tot] = MP(cnt[0], cnt[1]);
        }
    }
    if(f == false) {
        cout << -1 << '\n';
        return;
    }
    dp[0][0] = 1;
    for(int i = 1; i <= tot; i++) {
        for(int j = 0; j <= n; j++) {
            if (j >= num[i].fi) dp[i][j] |= dp[i - 1][j - num[i].fi];
            if (j >= num[i].se) dp[i][j] |= dp[i - 1][j - num[i].se];
        }
    }
    int ans = 1e9;
    for(int i = 0; i <= n; i++) {
        if(dp[tot][i]) {
            ans = min(ans, i * (i - 1) / 2 + (n - i) * (n - i - 1) / 2);
        }
    }
    cout << ans << '\n';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
#ifdef Local
    freopen("../input.in", "r", stdin);
    freopen("../output.out", "w", stdout);
#endif
    while(cin >> n >> m) run();
    return 0;
}

F - Eating Symbols Hard

鸽了好久,终于来补了= =

题意:
给出一个字符串含有">,<,+,-"四种字符,每种字符代表一种操作,字符串长度不超过\(10^5\)
先有一个初始全为\(0\)的无限长的数组,起点为\(0\)。"+"代表当前位置加一,"-"与之相反;">"代表往右边走一步,"<"代表往左边走一步。
现问多少区间\([l,r]\),只执行该区间内的操作,得到的数组能与执行\([1,n]\)的操作得到的想同。

思路:
感觉题意说了一大堆,可能我表述有点问题= =
可以考虑字符串哈希,哈希函数设计为:
\[ h(a)=\sum a_ix^i \]
之后有点不好表述了(果真我表述能力有问题),可以参见代码,代码还是比较好懂的。
处理区间hash值时注意\(hs[l]-hs[r+1]=hs[1]*pos[l-1]\)这个等式,具体含义可以看代码,这里直接相减是计算上前面那一部分的移动的。
反正很巧妙QAQ

Code

#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
//#define Local
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int N = 250005, P1 = 1e9 + 7, P2 = 1e9 + 9;

ll qpow(ll a, ll b, ll c) {
    ll ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % c;
        a = a * a % c;
        b >>= 1;
    }
    return ans;
}

char s[N];
int n;

struct rolling_hash{
    ll a, b;
    rolling_hash() {
        a = b = 0;
    }
    rolling_hash(ll x) {
        a = x % P1;
        b = x % P2;
    }
    rolling_hash(ll x, ll y) {
        a = x % P1;
        b = y % P2;
    }
    rolling_hash operator + (const rolling_hash& A) const {
        return rolling_hash(a + A.a, b + A.b);
    }
    rolling_hash operator - (const rolling_hash& A) const {
        return rolling_hash(a - A.a + P1, b - A.b + P2);
    }
    rolling_hash operator * (const rolling_hash& A) const {
        return rolling_hash(a * A.a, b * A.b);
    }
    ll get() {
        return a * P2 + b;
    }
}hs[N], pos[N];

rolling_hash X = 1000003;
rolling_hash invX = rolling_hash(qpow(X.a, P1 - 2, P1), qpow(X.b, P2 - 2, P2));

unordered_map <ll, int> mp;

void run() {
    mp.clear();
    cin >> s + 1;
    pos[0] = 1;
    for(int i = 1; i <= n; i++) {
        pos[i] = pos[i- 1];
        if(s[i] == '>') {
            pos[i] = pos[i - 1] * X;
        } else if(s[i] == '<') {
            pos[i] = pos[i - 1] * invX;
        }
    }
    hs[n + 1] = 0;
    for(int i = n; i >= 1; i--) {
        hs[i] = hs[i + 1];
        if(s[i] == '+') {
            hs[i] = hs[i] + pos[i];
        } else if(s[i] == '-') {
            hs[i] = hs[i] - pos[i];
        }
    }
    ll ans = 0;
    ++mp[hs[n + 1].get()];
    for(int i = n; i >= 1; i--) {
        rolling_hash now = hs[i] - hs[1] * pos[i - 1];
        ans += mp[now.get()];
        ++mp[hs[i].get()];
//        cout << ans << '\n';
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
#ifdef Local
    freopen("../input.in", "r", stdin);
    freopen("../output.out", "w", stdout);
#endif
    while(cin >> n) run();
    return 0;
}

转载于:https://www.cnblogs.com/heyuhhh/p/11594640.html

您可能感兴趣的与本文相关的镜像

Seed-Coder-8B-Base

Seed-Coder-8B-Base

文本生成
Seed-Coder

Seed-Coder是一个功能强大、透明、参数高效的 8B 级开源代码模型系列,包括基础变体、指导变体和推理变体,由字节团队开源

内容概要:本文提出了一种基于改进扩散模型的高海拔地区新能源高波动出力场景生成方法,并提供了完整的Python代码实现。该方法针对高海拔地区风能、光伏等新能源出力波动剧烈、不确定性高的特点,通过优化扩散模型的结构与训练策略,有效捕捉历史数据的概率分布特征与时序相关性,从而生成高质量、多样化的出力场景。文中详细阐述了模型的数学推导、网络架构设计、损失函数优化及采样算法改进,并通过实验证明其在拟合精度、场景多样性与稳定性方面优于传统生成模型,为电力系统在高比例新能源接入下的规划、调度与风险评估提供了可靠的场景输入支持。; 适合人群:具备一定Python编程能力和机器学习基础,从事新能源发电预测、电力系统分析、智能优化、场景生成等方向研究的科研人员、高校研究生及工程技术人员。; 使用场景及目标:①用于高海拔地区风电、光伏出力的不确定性建模与多场景生成;②支撑含高渗透率新能源的电力系统随机优化调度、鲁棒决策与风险评估;③为相关学术研究、论文复现与算法改进提供可运行的技术方案与代码基础; 阅读建议:建议读者结合所提供的完整资源(代码、数据集、说明文档)进行实践操作,重点关注扩散模型的前向加噪与反向去噪过程的设计细节,以及如何将其适配于新能源时序数据的生成任务,通过参数调优与对比实验深入理解模型的生成机制与性能边界。
内容概要:本文围绕基于静态约束法的配电网电动汽车接入容量评估展开研究,提出了一种在新型电力系统背景下评估主动配电网对电动汽车承载能力的方法。研究通过构建数学模型,结合潮流计算与关键约束条件(如电压越限、线路过载等),量化分析配电网可承受的最大电动汽车充电负荷容量,旨在识别规模化电动汽车接入带来的潜在运行风险,并为电网规划与运行提供科学依据。文中配套提供了完整的Matlab代码实现,便于仿真验证与结果复现。此外,该研究与分布式光伏承载力评估、电动汽车可调能力分析等方向形成技术联动,展现了多主题协同的研究体系。; 适合人群:具备电力系统分析基础理论知识及Matlab编程能力的高校研究生、科研机构研究人员,以及从事新能源并网、智能配电网规划与运行等相关领域的工程技术人员。; 使用场景及目标:①用于学术研究中的模型复现与论文撰写支撑;②评估实际配电网中电动汽车大规模接入的可行性与安全边界,指导充电基础设施布局;③作为高校教学案例,帮助学生深入理解电网承载力评估的核心原理、建模方法与仿真技术; 阅读建议:建议结合文中提及的相关研究方向(如二阶锥规划、多面体聚合方法等)进行对比学习,充分利用所提供的Matlab代码与网盘资料开展仿真实验,重点关注约束条件的设定逻辑与潮流计算模块的实现细节,以深化对评估模型机理与工程应用价值的理解。
内容概要:本文围绕“考虑隐私保护的分布式联邦学习电力负荷预测研究”展开,提出了一种基于Python实现的联邦学习框架,旨在解决居民或行业电力负荷预测中用户电表数据隐私泄露的风险。该研究通过构建分布式机器学习模型,使各参与方在不共享原始数据的前提下协同训练全局模型,有效实现了数据“可用不可见”。文中详细阐述了联邦学习的整体架构设计、本地模型训练流程、参数加密传输与安全聚合机制,并结合差分隐私等技术进一步增强系统的隐私保护能力。同时,研究利用真实电力负荷数据集进行了实验验证,展示了方法在预测精度与隐私保障之间的良好平衡,并提供了完整的代码实例与复现指南,便于后续研究与应用拓展。; 适合人群:具备一定机器学习基础和电力系统背景知识,从事智慧能源、隐私计算或人工智能相关方向研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 实现跨区域、跨主体的电力负荷协同预测,打破数据孤岛;② 在确保用户用电数据隐私安全的前提下提升负荷预测准确性;③ 推动联邦学习在智能电网、需求响应、虚拟电厂等场景中的实际部署与应用。; 阅读建议:建议结合文中提供的Python代码与网盘资料进行动手实践,重点关注联邦学习的通信轮次设计、模型聚合算法(如FedAvg)的实现细节以及差分隐私噪声添加策略,深入理解其对模型性能与隐私强度的影响,为进一步优化与创新奠定基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值