华为OD机考题目《用连续自然数之和来表达整数》100分题目


牛客上看到这么一个帖子:https://www.nowcoder.com/discuss/625512
里面三道题,先做了第一道:


读了一下题目,说是给一个数,让你输出它的所有可由联系自然数的和表示的情况,和数量。
根据题目中给出的输出样例,如果存在多组输出的话,应该是按照数字个数从少到多来输出,最后再补充一个 Result=X,其中X代表有多少组。

为此,我好好回忆了一把高中数学学习序列的时候,如果从m  一直加连续的数,加到n,那么结果是“首尾相加 乘以  个数  除以 2”
即       

如果 改为:  从  m开始加,一共加 i个数,结果是:





于是,根据这个公式,反推出 m,得到:



于是,我让i 从 2 开始  (没必要从1开始,因为1个数相加得到t的话,那么 m一定等于 t ),只要能让m是个整数,没有小数点,那就是满足条件的解。

m是整数的条件是 里面所有除法都能整数,包括:

             和            


如果满足,则 t = m+(m+1)+(m+2)+……+(m+i-1)

于是代码就出来了:

#include<iostream>
using namespace std;
int main() 
{
    int t;
    cin >> t;

    //首先将 t=t打印出来
    cout << t << "=" << t << endl;

    int cnt = 1;
    // i 表示组成t的连续的数字的个数,从 2个开始,因为1个已经打印过了。
    for (int i = 2; i *(i - 1)/2 < t ; i++)
    {
        int m = 0;
        /*
        根据数学公式,从m 连续加到n,结果是 t = (m+n)(n-m+1)/2,
        如果从 m 开始 加 i个数,即从 m 加到 m+i-1 ,得到 t = (2m+i-1)*i/2
        因此推导出, m = (2*t/i - i + 1 )/ 2 , 
        如果 m的计算公式中, 2*t/i 没有出现小数点,且 m也没出现小数点,则这就是一个可用的解
        */
        if (2 * t % i == 0 && (2 * t / i - i + 1) % 2 == 0) 
        {
            m = (2 * t / i - i + 1) / 2;
            cnt++;
            cout << t << "=";
            for (int j = 1; j < i; j++)
                cout << m++ << "+";
            cout << m << endl;
        }
    }

    cout << "Result:" << cnt;
    return 0;
}




经过自测运行结果:
       




不得不说,这是一道纯数学题。

在做机考的时候,还是要准备好纸笔,作用很大的。

今天的分享就到此为止啦,欢迎留下更多华为OD机考真题,共同挑战。







全部评论
3 回复 分享
发布于 2022-05-31 23:10
帮我看看
1 回复 分享
发布于 2022-05-31 20:28
为啥第一个for循环i*(i-1)/2 <t呢?
点赞 回复 分享
发布于 2024-09-20 11:27 四川

相关推荐

劝退式:感觉有人回才是不正常的
点赞 评论 收藏
分享
评论
5
3
分享

创作者周榜

更多
牛客网
牛客企业服务