CF936 div2 B. Maximum Sum

You have an array a of n integers.

You perform exactly k operations on it. In one operation, you select any contiguous subarray of the array a (possibly empty) and insert the sum of this subarray anywhere in the array.

Your task is to find the maximum possible sum of the array after such operations.

As this number can be very large, output the answer modulo 109+7.

Reminder: the remainder of a number x modulo p is the smallest non-negative y such that there exists an integer q and x=p⋅q+y.

Input

Each test consists of several test cases. The first line contains a single integer t(1≤t≤10^4) — the number of test cases. Then follows the description of the test cases.

The first line of each test case contains two integers n and k (1≤n,k≤2⋅10^5) — the length of the array a and the number of operations, respectively.

The second line of each test case contains n integers a1,a2,…,an (−10^9≤ai≤10^9) — the array a itself.

It is guaranteed that the sum of the values of n and k for all test cases does not exceed 2⋅1052⋅105.

Output

For each test, output a single integer — the maximum sum of the array that can be obtained after k operations modulo 10^9+7

翻译

您有一个包含n个整数的数组a。

您在它上面执行精确地k次操作。在一次操作中,您选择数组a的任意连续子数组(可能为空),并将此子数组的总和插入数组中的任意位置。

您的任务是找到在k次操作后数组的最大可能总和。

由于这个数字可能非常大,输出答案模109+7。

提醒:数字x模p的余数是最小的非负y,使得存在整数q使得x=p⋅q+y。

输入 

每个测试包含多个测试用例。第一行包含一个整数t(1≤t≤10^4) — 测试用例的数量。然后是测试用例的描述。

每个测试用例的第一行包含两个整数n和k(1≤n,k≤2⋅10^5) — 数组a的长度和操作次数。

每个测试用例的第二行包含n个整数a1,a2,…,an(−10^9≤ai≤10^9) — 数组a本身。

保证所有测试用例中n和k的值之和不超过2⋅1052⋅105。

输出 

对于每个测试用例,输出一个整数 — 在k次操作后可以获得的数组的最大总和,模10^9+7。

解题思路

本题考察了动态规划,动态规划求出最大连续子序列之后,一直成2取余,最后再减去第一次

需要注意的是,初始的数可能全是负数,而且负数和的绝对值可能大于1e9+7,需要考虑对负数取余数的情况

#include<stdio.h>
long long  mod = 1e9 + 7;
long long max(long long x, long long y)
{
	if (x > y)
		return x;
	else
		return y;
}
long long dp[200010], a[200010];

int main()
{
	int t, n, k;
	scanf("%d", &t);
	while (t--)
	{
		long long s = -1e10, p = 0, he = 0;
		scanf("%d %d", &n, &k);
		for (int i = 1; i <= n; i++)//dp递推
		{
			scanf("%lld", &a[i]);
			he += a[i];
			dp[i] = max(dp[i - 1] + a[i], a[i]);
			if (dp[i] > s)
			{
				s = dp[i];
				p = i;
			}
		}
		if (s < 0)
		{
			long long ans = ((he % mod) + mod) % mod;
			printf("%lld\n", ans);
		}
		else
		{
			long long ans = dp[p];
			for (int i = 1; i <= k; i++)
				ans = (2 * ans) % mod;
			ans = ((ans - dp[p] + he) % mod + mod) % mod;
			printf("%lld\n", ans);
		}
	}
	return 0;
}

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

3分人生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值