C++每日一练:三而竭(巧用暴力解法)

本文介绍了如何解决一个关于任务分配的编程问题,题目名为“三而竭”。作者探讨了使用暴力解法的局限性,然后通过优化循环和计算方法提高了解题效率,包括用log运算代替pow函数,以及调整搜索范围来减少计算次数。最终,虽然作者承认可能存在更优的数学解法,但通过这些优化,解题方案能够在限制时间内找到答案。

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


前言

又来练一波,今天的题目很玄。幸运数字肯定题目有问题,那描述也很神,让人看不明白前后怎么相同。我试了各种情况都只有40%,就略过了。
在这里插入图片描述
三而竭,这题有点难度。就做它了!


提示:以下是本篇文章正文内容,下面代码已通过测试,可供参考

一、题目

题目描述
一鼓作气再而衰三而竭。 小艺总是喜欢把任务分开做。 小艺接到一个任务,任务的总任务量是n。 第一天小艺能完成x份任务。 第二天能完成x/k。 。。。 第t天能完成x/(k^(t-1))。 小艺想知道自己第一天至少完成多少才能完成最后的任务。

输入描述:
第一行输入整数n,k。(1<=n<=1e9,2<=k<=10)

输出描述:
输出x的最小值。

示例:输入:59 9 输出: 54

二、解题过程

0.分析

暴力显然不可行的,从题目来看:一是要找到一个合适天数t值范围,二是要找到一个合适的工作量范围,这里用变量x来说明,显然这题可以理解成n/k^t=1的问题,所以t值和k有关,和n有关,先尝试了二分查找,来得到t,一样有pow函数计算,比暴力好不了多少。还不如解开k的n次方,用k*=k来代替,这种方法得到了70%的正确,很显然在极端情况,我的t取值少了。但是这个办法t再加1,就超时!这办法乘法计算太多,再改成t=log2(n),这回计算一次完事!还是只有70%,t值还是少了点,再加1,一样过不了计算。
t肯定要取t=log2(n)+1的,再优化其它地方去,另一个值就是x工作量的范围了,暴力从1到n,显然起始值太小,改n/2,OK!

1.代码

代码如下(示例):

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <cmath>

int sum(int t, int k, int x){
    int res = 0, pow_k=1;
    for (int i=1; i<=t; ++i){
        res += x/pow_k;
        pow_k *= k;
    }
    return res;
}

int solution(int n, int k){
    int result=n;
    // TODO:
    int tmp = 0;
    int t_day=1 ;
    t_day = log2(n)+1;
    for (int t=1; t<=t_day; ++t){
        for (int x=n/2; x<=n; ++x){
            tmp = sum(t,k, x);
            if(tmp>=n){
                if(x<result) result=x;
                else if (x>=result) break;
            }
        }
    }
    return result;
}

int main() {
    int n;
    int k;
    std::cin>>n;
    std::cin>>k;
    int result = solution(n, k);
    std::cout<<result<<std::endl;
    return 0;
}

总结

这是一道难得的好题,难度系数还是有点高的。总体解题思路还是暴力凑数字。相信应该是存在数学解法的,但笔者那点高等数学知识都已经还给老师了。当不了数学家,就只好暴力了。很显然这里有三个嵌套循环,太暴力了肯定是过不了的。所以取值范围是这个解法的关键。

1、一是时间长度t,表示了天数。它的最大值是很难确定的,从n/k^t=1来看,这里k的最小值就是2,那么t表示的时间长度就可以用log2(n)来求出最大值。所以代码中的t_day的最大范围就得到了。

2、二就是n的最小值取值范围,这个比较好理解。肯定不会少于一半的。直接定为n/2就行。

3、此解法的第三点就是要拆开pow计算,因为pow太费时了,循环中不停的计算。所以这里写了一个单独的sum函数来求到t天的工作量。因为第一天是k的0次方,所以值为1。第二天就是k的一次方,第三天是k的2次方,pow本身就是乘法。在sum函数中,就直接用乘等来写了,会比每次循环计算pow快很多。

4、solution函数其实就是一个凑数字的过程。通过以上的几点分析,写出这个凑数字的方法还是很容易的。虽然它有三重嵌套循环,但还是可以在规定的时间内解出来,关键就是以上三点。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无证的攻城狮

如本文对您有用,大爷给打个赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值