蓝桥 和与乘积 模拟 前缀和 找规律 java

🍑 和与乘积

在这里插入图片描述
输入

4
1 3 2 2

输出

6

在这里插入图片描述


🍑 思路

🍤 对数组的 1 和 非1 数据进行处理
🍤 a[i]:存新数组后的每一个数(原数组非1的数)
🍤 num[i]:表示第 i 个数左边有多少个连续的1
🍑 sum[i]:表示第 i 个非1数左边的所有数的和(包含第i个数)

🍑 AC code

import java.util.*;

public class Main
{
	static int N = 200010;
	static int[] a = new int[N];// 记录处理过后的新序列
	static long[] sum = new long[N];// 记录新序列的前缀和
	static long[] num = new long[N];// num[i] 表示 a[i]左边有多少个连续的 1
	static int k = 1;// 新数组的下标(计数)

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		for (int i = 1; i <= n; i++)
		{
			int t = sc.nextInt();
			if (t == 1)
			{
				num[k]++;
				sum[k]++;
			} else
			{
				sum[k] += sum[k - 1] + t;
				a[k] = t;
				k++;
			}

		}
		long ans = n;// 一个元素也是一个合法区间
//		总共只有 k-1 个元素,但后边还可能有1,sum[k]记录的是后边的1
		long max = sum[k - 1] + sum[k];// 所有元素的总和
		for (int l = 1; l < k; l++)// 枚举区间左端点
		{
			long p = a[l];// p 记录乘积
			for (int r = l + 1; r < k; r++)// 枚举区间右端点
			{
				p *= a[r];// p 记录的是区间[l,r]的乘积
				if (p > max)// 只要超过所有元素的和,那就不肯相等的,直接跳出
					break;
//				t = 乘积 - [l,r]的和 - l左边的1的个数
				long t = p - (sum[r] - sum[l - 1] - num[l]);// t表示需要补的 1 的个数
				if (t == 0)// 刚刚好
					ans++;
				// 试试拿右边的1凑凑?
				else if (num[l] + num[r + 1] >= t && t > 0)
				{
//					左边最多贡献的 1 的个数(受 需要1的个数t 和 左边有连续1的个数num[l] 的影响)
					long left = Math.min(t, num[l]);
//					右边最多贡献的 1 的个数(受 需要1的个数t 和 右边有连续1的个数num[r+1] 的影响)
					long right = Math.min(t, num[r + 1]);
//					在 left + right 个 1 中选择 t 个连续的 1
//					相当于t为一个窗口长度,(left + right - t)表示窗口可以走到哪里
//					+1 是因为窗口的起点也是一种方案
					ans += left + right - t + 1;
				}
			}
		}
		System.out.println(ans);
	}
}

🍑 暴力 (20%)

import java.io.*;

public class Main
{
	static int N = 200010;
	static int[] a = new int[N];
	static long[] s = new long[N];
	static long[] j = new long[N];

	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

	public static void main(String[] args) throws IOException
	{
//		Scanner sc = new Scanner(System.in);
//		int n = sc.nextInt();
		int n = Integer.parseInt(in.readLine());
		String[] ss = in.readLine().split(" ");
		for (int i = 1; i <= n; i++)
//			a[i] = sc.nextInt();
			a[i] = Integer.parseInt(ss[i - 1]);

//		预处理前缀和数组
		for (int i = 1; i <= n; i++)
			s[i] = s[i - 1] + a[i];
//		预处理前缀积
		j[0] = 1;
		for (int i = 1; i <= n; i++)
			j[i] = j[i - 1] * a[i];

		long ans = 0;
		for (int l = 1; l <= n; l++)
		{
			for (int r = l; r <= n; r++)
			{
				if (s[r] - s[l - 1] == j[r] / j[l - 1])
					ans++;
			}
		}
		System.out.println(ans);
	}
}

👨‍🏫 鲸落的题解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值