C - Sigma Problem(AtCoder Beginner Contest 353)

题目的链接:

C - Sigma Problem (atcoder.jp)

题目:

样例:

 题目大致含意:

给你n个数,让你对这n个数进行操作,比如当前是第i个,那么让a[i] 和 后面的每个数进行相加,
例如a[i] + a[i + 1] 注意的是a[i] + a[i + 1]的结果要进行取模 同理进行操作 (a[i] + a[i + 2]) % mod 输出的结果是 把这些运算后的数 加起来 注意的是 这些加起来的数就不再进行取模操作了

分析:

本题考查的是取模的一些操作,可以先考虑先不去取模着,先把这些结果加在一起 这需要利用前缀和的思想 推导的公式是: ret += (n - i) * a[i] + (sum[n] - sum[i]); 前提是 先把前缀和给提前预处理好,然后取模 取模其实就是减去多个 mod,要去知道是哪些(a[i] + a[j]) 他们是大于1e8了 然后我再减去 就可以了 那怎么快速知道 有多少个(a[i] + a[j])是大于1e8的!可以枚举每个a[i] 然后二分找到第一个大于等于(1e8 - a[i])的数的位置 那么(n - 这个位置)就是这n个数里面和当前的a[i] 相加是大于1e8的 那么我就直接ret - 1e8*个数

代码:

// package AtCoderBeginnerContest353;

import java.util.Arrays;
import java.util.Scanner;

public class C {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long mod = (long) 1e8;
		long ret = 0;
		long[] a = new long[n + 10];
		long[] sum = new long[n + 10];
		
		//就是二分
		for(int i = 1; i <= n; i ++ ) {
			a[i] = sc.nextLong();
			// 也是要利用前缀和的思想
			sum[i] = sum[i - 1];
			sum[i] += a[i];
		}
		for(int i = 1; i <= n; i ++ ) {
			ret += (n - i) * a[i] + (sum[n] - sum[i]);
		}
	//	System.out.println("ret = " + ret); // ret出现了问题
		
		Arrays.sort(a, 1, n + 1);
//		for(int i = 1; i <= n; i ++ ) {
//			System.out.print(a[i] + " ");
//		}
		for(int i = 1; i <= n; i ++ ) {
			int l = i, r = n + 1;
			long x = mod - a[i]; // 这个是要找的 找到第一个大于等于x的位置
			while(l + 1 < r) {
				int mid = l + r >> 1;
				if(a[mid] < x)l = mid;
				else r = mid;
			}
			//System.out.println("i = " + i + " l = " + l);
			// l + 1 是最后的答案
			ret -= (mod * (n - l));
		}
		System.out.print(ret);
	}
}

运行的结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

FindYou.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值