循环求和

[题目链接](https://www.nowcoder.com/practice/f1725df80ee04cfebb6300f27c3d6464)

思路

牛牛把自然数序列里所有偶数加了负号,变成 给定区间 ,要求这段数的和。

找前缀和的规律

先不急着算区间和,想一想前缀和 长什么样。把前几项列出来:

$$

$$

规律很明显了:

  • 奇数时,
  • 偶数时,

为什么呢?偶数个数可以两两配对 ,每一对的和都是 ,共 对,所以 。奇数就是在偶数基础上再加一个正数 ,即

区间和

有了前缀和公式, 的答案就是 搞定。

注意 ,在代码里要处理一下边界。

代码

#include <bits/stdc++.h>
using namespace std;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        long long l,r;
        scanf("%lld%lld",&l,&r);
        auto S = [](long long n) -> long long {
            if(n <= 0) return 0;
            if(n % 2 == 0) return -n / 2;
            else return (n + 1) / 2;
        };
        printf("%lld\n", S(r) - S(l - 1));
    }
    return 0;
}
import java.util.Scanner;
import java.io.*;

public class Main {
    static long S(long n) {
        if (n <= 0) return 0;
        if (n % 2 == 0) return -n / 2;
        else return (n + 1) / 2;
    }
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int t = Integer.parseInt(br.readLine().trim());
        StringBuilder sb = new StringBuilder();
        while (t-- > 0) {
            String[] parts = br.readLine().trim().split("\\s+");
            long l = Long.parseLong(parts[0]);
            long r = Long.parseLong(parts[1]);
            sb.append(S(r) - S(l - 1)).append('\n');
        }
        System.out.print(sb);
    }
}
import sys
input = sys.stdin.readline

def S(n):
    if n <= 0:
        return 0
    if n % 2 == 0:
        return -n // 2
    else:
        return (n + 1) // 2

t = int(input())
out = []
for _ in range(t):
    l, r = map(int, input().split())
    out.append(str(S(r) - S(l - 1)))
print('\n'.join(out))
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin });
const lines = [];
rl.on('line', line => lines.push(line.trim()));
rl.on('close', () => {
    let idx = 0;
    const t = parseInt(lines[idx++]);
    const res = [];
    function S(n) {
        if (n <= 0n) return 0n;
        if (n % 2n === 0n) return -n / 2n;
        else return (n + 1n) / 2n;
    }
    for (let i = 0; i < t; i++) {
        const parts = lines[idx++].split(/\s+/);
        const l = BigInt(parts[0]);
        const r = BigInt(parts[1]);
        res.push((S(r) - S(l - 1n)).toString());
    }
    console.log(res.join('\n'));
});

复杂度分析

  • 时间复杂度,每组查询 计算。
  • 空间复杂度(不计输入输出缓冲)。