备战蓝桥杯day4

本文主要记录笔者备战蓝桥杯的过程。

目录

前言

一、基础题:刷题统计

二、进阶题:选素数

总结


前言

本文主要记录笔者备战蓝桥杯的过程,包括一道基础题和一道进阶题。


一、基础题:刷题统计

我先把题目测试链接粘贴在下面:

P8780 [蓝桥杯 2022 省 B] 刷题统计 - 洛谷

题目详细叙述如下:

我的核心思路是先整后零计算消耗完总量n的总天数,先根据每周前5天每天消耗a、后2天每天消耗b的规则,算出单周总消耗5*a + 2*b,通过整数除法得到能完整消耗的周数weeks,并从n中扣除这些整周的消耗量,再遍历一周7天,按前5天扣a、后2天扣b的规则逐天处理剩余的n,统计不足一周的消耗天数days,最终总天数为7*weeks + days,代码如下:

cpp 复制代码
#include <stdio.h>

int main(){
    long long a = 0;
    long long b = 0;
    long long n = 0;
    scanf("%lld %lld %lld", &a, &b, &n);
    long long weeks = n / (5 * a + 2 * b);
    n -= (weeks * (5 * a + 2 * b));
    int days = 0;
    for(int i = 0; i < 7; i++){
        if(n > 0){
            if(i < 5){
                n -= a;
            }else{
                n -= b;
            }
            days++;
        }else{
            break;
        }
    }
    printf("%lld", 7 * weeks + days);
}

二、进阶题:选素数

我先把题目测试链接粘贴在下面:

P8795 [蓝桥杯 2022 国 A] 选素数 - 洛谷

题目详细叙述如下:

核心思路是反向推导+素因数限定范围+最小化验证,首先明确选小于当前数的素数p,补到p的倍数的操作逻辑,反向来看,若操作结果是res,则操作前的数需在(res-p, res]之间(且p是res的素因数、p小于操作前的数)。解题时,先从最终结果n出发,找出n的所有素因数(作为第二次操作的候选素数p1),据此确定第二次操作前数y的合法范围(需满足y>p1且y∈(n-p1, n]),遍历这些y并验证其选p1操作后是否得到n;再对每个合法的y,找出y的所有素因数(作为第一次操作的候选素数p2),确定第一次操作前数x的合法范围(需满足x>p2且x∈(y-p2, y]),遍历x验证其选p2操作后是否得到y,过程中记录最小的x;最终若找到最小x则输出,无合法值则输出-1。代码如下:

cpp 复制代码
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>

// 计算两个数的最大值(long long类型)
long long max(long long a, long long b) {
    return a > b ? a : b;
}

// 判断一个数是否为素数
bool is_prime(long long num) {
    if (num < 2) return false;
    if (num == 2) return true;
    if (num % 2 == 0) return false;
    for (long long i = 3; i * i <= num; i += 2) {
        if (num % i == 0) return false;
    }
    return true;
}

// 获取一个数的所有不同素因数(存到factors数组,count为因数数量)
void get_prime_factors(long long num, long long factors[], int *count) {
    *count = 0;
    if (num < 2) return;
    // 处理素因数2
    if (num % 2 == 0) {
        factors[(*count)++] = 2;
        while (num % 2 == 0) num /= 2;
    }
    // 处理奇数素因数
    for (long long i = 3; i * i <= num; i += 2) {
        if (num % i == 0) {
            factors[(*count)++] = i;
            while (num % i == 0) num /= i;
        }
    }
    // 剩余的数本身是素因数
    if (num > 1) factors[(*count)++] = num;
}

// 模拟单次操作:num选素数p后得到的结果
long long get_oper_result(long long num, long long p) {
    if (p >= num || !is_prime(p)) return -1; // 非法输入(p不满足条件)
    // 计算≥num的最小p的倍数:(num + p - 1)/p 是向上取整的结果
    return (num + p - 1) / p * p;
}

int main() {
    long long n;
    scanf("%lld", &n);

    long long min_x = LLONG_MAX; // 初始化最小x为极大值
    long long n_factors[100];    // 存储n的素因数
    int n_factor_count = 0;
    get_prime_factors(n, n_factors, &n_factor_count);

    // 遍历n的每个素因数(作为第二次操作的p1)
    for (int i = 0; i < n_factor_count; i++) {
        long long p1 = n_factors[i];
        // 计算第二次操作前y的合法范围:(n-p1, n] 且 y > p1
        long long y_start = max(p1 + 1, n - p1 + 1);
        long long y_end = n;
        if (y_start > y_end) continue; // 无合法y,跳过

        // 遍历所有可能的y
        for (long long y = y_start; y <= y_end; y++) {
            // 验证y经过p1操作是否得到n
            if (get_oper_result(y, p1) != n) continue;

            // 获取y的所有素因数(作为第一次操作的p2)
            long long y_factors[100];
            int y_factor_count = 0;
            get_prime_factors(y, y_factors, &y_factor_count);
            if (y_factor_count == 0) continue;

            // 遍历y的每个素因数p2,找第一次操作的x
            for (int j = 0; j < y_factor_count; j++) {
                long long p2 = y_factors[j];
                // 计算第一次操作前x的合法范围:(y-p2, y] 且 x > p2
                long long x_start = max(p2 + 1, y - p2 + 1);
                long long x_end = y;
                if (x_start > x_end) continue;

                // 遍历x找最小合法值
                for (long long x = x_start; x <= x_end; x++) {
                    if (get_oper_result(x, p2) == y) {
                        if (x < min_x) {
                            min_x = x;
                        }
                        break; // x从小到大遍历,第一个即为当前p2下的最小x
                    }
                }
            }
        }
    }

    // 输出结果
    if (min_x == LLONG_MAX) {
        printf("-1\n");
    } else {
        printf("%lld\n", min_x);
    }

    return 0;
}

总结

本文主要记录笔者备战蓝桥杯的过程,包括一道基础题和一道进阶题的讲解。

相关推荐
魂梦翩跹如雨21 小时前
P10424 [蓝桥杯 2024 省 B] 好数——Java解答
java·蓝桥杯
小年糕是糕手1 天前
【C++】类和对象(四) -- 取地址运算符重载、构造函数plus
c语言·开发语言·数据结构·c++·算法·leetcode·蓝桥杯
_OP_CHEN1 天前
【算法基础篇】(二十四)数据结构之并查集拓展:从 “单一关系” 到 “复杂约束”,这篇带你解锁进阶玩法!
数据结构·蓝桥杯·并查集·算法竞赛·acm/icpc·带权并查集·扩展域并查集
魂梦翩跹如雨2 天前
P8615 [蓝桥杯 2014 国 C] 拼接平方数——Java解答
java·c语言·蓝桥杯
迈巴赫车主2 天前
蓝桥杯20534爆破 java
java·数据结构·算法·职场和发展·蓝桥杯
是苏浙2 天前
蓝桥杯备战day2
蓝桥杯
量子炒饭大师2 天前
David自习刷题室——【蓝桥杯刷题备战】乘法表
c语言·c++·git·职场和发展·蓝桥杯·github·visual studio
_OP_CHEN2 天前
【算法基础篇】(二十三)数据结构之并查集基础:从原理到实战,一篇吃透!
数据结构·算法·蓝桥杯·并查集·算法竞赛·acm/icpc·双亲表示法
良木生香3 天前
【程序设计】P8772 [蓝桥杯 2022 省 A] 求和
c语言·算法·职场和发展·蓝桥杯