CSDN 编程竞赛·第五期总结

本文是作者首次参加CSDN编程竞赛的总结,分享了四道题目的解题思路和代码实现。第一题利用唯一分解定理找到因子个数为n的最小整数;第二题通过循环找出最高面额的货币种类;第三题通过递归解决字符串反转问题;第四题通过等比数列计算最小初始任务量。文章适合对算法感兴趣的编程爱好者阅读。
摘要由CSDN通过智能技术生成

CSDN 编程竞赛·第五期为笔者参加的第一次 CSDN 编程竞赛,由于报名人数不多,笔者还是有幸凭借自己的三脚猫功夫,拿到了不错的名次,特此写博客一篇,进行总结。

竞赛成绩

本次编程竞赛一共4题,笔者只完美通过2题,现对比赛的4道题目进行总结。

寻因找祖

题目描述:
寻找因子个数为n的最小整数x。

题干十分简略,像笔者这种萌新只能想到暴力法,通过率只有50%。

赛后了解了其他思路:
根据唯一分解定理,如果一个数n可以表示成 n = p 1 a 1 ∗ p 2 a 2 ∗ . . . ∗ p k a k n=p_1^{a_1}*p_2^{a_2}*...*p_k^{a_k} n=p1a1p2a2...pkak的形式那么n的因数的个数为 ( a 1 + 1 ) ∗ ( a 2 + 1 ) ∗ . . . ∗ ( a k + 1 ) (a_1+1)*(a_2+1)*...*(a_k+1) (a1+1)(a2+1)...(ak+1)
根据这个思路,我们可以得到以下代码:

#include <iostream>
#include <string>
#include <cstring>
#include <sstream>
#include <vector>

const int maxn = 1e6 + 5;
int min_num[maxn], cnt[maxn];

int solution(int n)
{
    int result;
    memset(min_num, -1, sizeof(min_num));
    for (int i = 1; i < maxn; i++)
        for (int j = i; j < maxn; j += i)
            cnt[j]++;
    for (int i = 1; i < maxn; i++)
        if (min_num[cnt[i]] == -1)
            min_num[cnt[i]] = i;
    result = min_num[n]
    return result;
}

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

其中cnt[i]i的因子个数,min_num[n]为因子个数为n的最小整数。


通货膨胀-x国货币

题目描述:
X国发行货币最高面额为n。 次高面额为n的因子。 以此类推。 X国最多发行多少种货币。

本题时间要求比较低,笔者的做法:

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

int solution(int n)
{
    if (n == 1)
        return 1;
    int result = 0;
    for (int i = n / 2; i >= 1; i--)
    {
        if (n % i == 0)
        {
            result += 1 + solution(i);
            break;
        }
    }
    return result;
}

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

莫名其妙的键盘

题目描述:
有一个神奇的键盘,你可以用它输入a到z的字符,然而每当你输入一个元音字母(a,e,i,o,u其中之一)的时候,已输入的字符串会发生一次反转! 比方说,当前输入了tw,此时再输入一个o,此时屏幕上的字符串two会反转成owt。 现给出一个字符串,若用该键盘输入,有多少种方法可以得到?

题干还算比较长,但只是个普通的递归,笔者这题用的是Python:

class Solution:
    def __init__(self) -> None:
        pass

    def solution(self, str):
        if len(str) == 1:
            return 1
        result = 0
        if str[0] in ('a', 'e', 'i', 'o', 'u'):
            result += self.solution(str[1:][::-1])
        if str[-1] not in ('a', 'e', 'i', 'o', 'u'):
            result += self.solution(str[:-1])
        return result
    
if __name__ == "__main__":
    str = input().strip()
    s = Solution()
    result = s.solution(str)
    print(result)

三而竭

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

该题的测试用例为:n=59,k=9 输出 x=54

笔者开始是使用等比数列前n项和求极限来计算n,最后解出用例的x=53,猜测可能不能累加小数部分。

下面的代码是赛后笔者写的,笔者觉得应该是正确:

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

int solution(std::vector<int> &vec)
{
    int result;
    int n = vec.at(0);
    int k = vec.at(1);
    for (int i = n; i > 0; i--)
    {
        int sum = i;
        for (int j = k; i / j >= 1;j*=k)
        {
            sum += i / j;
        }
        if(sum < n)
        {
            result = i + 1;
            break;
        }
    }
    return result;
}

int main()
{
    std::vector<int> vec;
    std::string line_0, token_0;
    getline(std::cin >> std::ws, line_0);
    std::stringstream tokens_0(line_0);
    while (std::getline(tokens_0, token_0, ' '))
    {
        vec.push_back(std::stoi(token_0));
    }
    int result = solution(vec);
    std::cout << result << std::endl;
    return 0;
}

以上就是这次 CSDN 编程竞赛的全部内容了,如有错误,请读者指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小嗷犬

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值