华为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机考真题,共同挑战。