CF1946B Maximum Sum 題解

zhuluoan發表於2024-04-13

題目簡述

你有一個由 $n$ 個整陣列成的陣列 $a$。

你要對它進行 $k$ 次操作。在一次操作中,你選擇了陣列 $a$ 的任意連續子陣列(可能為空),並在陣列的任意位置插入了該子陣列的和。

你的任務是找出經過 $k$ 次操作後陣列的最大和。

題目分析

這道題顯然是一道貪心題。

對於第 $1$ 次操作,選擇的話肯定是選最大的好,所以我們會找出原序列的最大子段和進行插入,為了使下一次的插入子段更大,所以我們一定會插入原序列的最大子段和中。進行 $m$ 次操作,執行 $m$ 次上述操作即可。

直接模擬的話肯定不行,我們考慮找找規律,由於每次插入都是插入現在序列的最大子段和中,所以每次插入的值都是翻倍增長的,易發現這是一個等比數列的求和。我們如果模擬上述操作,複雜度為 $\mathcal{O}(m)$,可以接受。

最後注意取模。

程式碼

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+10,mod=1e9+7;
int n,k,a[N],T;
ll Max,f,sum,mul;
void solve()
{
	cin>>n>>k;
	Max=f=sum=0;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		f=max(a[i]*1ll,a[i]+f);
		Max=max(f,Max);
		sum+=a[i];
	}
	Max%=mod;
	sum=(sum%mod+mod)%mod;
	mul=1;
	for(int i=1;i<=k;i++)
	{
		sum=(sum+mul*Max%mod+mod)%mod;
		mul=mul*2%mod;
	}
	cout<<sum<<"\n";
}
int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>T;
    while(T--)
    {
    	solve();
	}
	return 0;
}

相關文章