题目---小Q定义了一种数列称为翻转数列: 给定整数n和m, 满足n能被2m整除。对于一串连续递增整数数列1, 2, 3, 4..., 每隔m个符号翻转一次, 最初符号为'-';。

题目:

小Q定义了一种数列称为翻转数列:
给定整数n和m, 满足n能被2m整除。对于一串连续递增整数数列1, 2, 3, 4…, 每隔m个符号翻转一次, 最初符号为’-‘;。

例如n = 8, m = 2, 数列就是: -1, -2, +3, +4, -5, -6, +7, +8.
而n = 4, m = 1, 数列就是: -1, +2, -3, + 4.
小Q现在希望你能帮他算算前n项和为多少。

看到这道题,首先想到的就是根据其符号的变化规律,用来判断当前的符号,依次将每个数相加,得到最后的结果。代码实现:

#include <iostream>
using namespace std;

long solution(long n, long m)
{
    long n1 = 1;
    long tmp = 1;
    int flag = -1;
    while (n1 <= n)
    {
        if (tmp <= m)
        {
            sum = sum + flag*n1;
            n1++;
            tmp++;
        }
        else
        {
            tmp = 1;
            flag = -flag;
        }
    }
    return sum;
}

int main()
{
    long n;
    long m;
    cin >> n;
    cin >> m;
    cout << solution(n, m) << endl;
    return 0;
}

写这个代码时,也是经过了好一番调试才成功,首先就是返回值的问题,由于题目要求的n的范围是最大是10的9次方,所以用int来表示就会出现溢出的情况。所以我们需要一个更大的数据类型,这时就需要使用long来作为该程序的数据类型。这是一个问题。在解决了这个问题之后,又有一个大问题,就是运行结果超时了。这时就需要检查一下考虑这个问题的思路了。应该是写的程序复杂了。
再考虑了一下之后,就又有了这样的想法,代码如下:

#include <iostream>
using namespace std;

long solution(long n,long m)
{
    long sum = 0;
    long n1 = 1;
    int flag = -1;
    while(n1 <= n)
    {
       sum = (((flag*n1+(n1+m-1)*flag)*m)/2)+sum;
        n1 += m;
        flag = -flag;
    }
    return sum;
}

int main()
{
    long n;
    long m;
    cin>>n;
    cin>>m;
    cout<<solution(n,m)<<endl;
    return 0;
}

这个代码也很好懂,因为这个数列总是除去符号位,数字总是每次加一,所以我们可以在小范围内用等差公式进行计算。就是在其符号位没有改变之前的这个小范围内。
例如:像是输入 8 2
数列就是:-1 -2 3 4 -5 -6 7 8
我们就能先算-1 -2的等差和再算3、4的,依次向下计算。

小结: 在做题时,要注意数值的取值范围,不能直接上来就是int类型。还有循环的边界条件得想清楚。

猜你喜欢

转载自blog.csdn.net/weixin_40331034/article/details/80357952
今日推荐