P8590 『JROI-8』这是新历的朝阳,也是旧历的残阳

题目背景

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

少女于海边伫立,凝视着落日最后的余晖
“已然过去了呢,旧历的一年…”

已获得转载授权。

题目描述

给定序列 {an}\{a_n\}{an},满足每一项都不小于前一项。对于所有不超过 kkk 的正整数 mmm,询问如果将 aaa 分成 mmm 段(可以有空段),并给从前往后第 iii 段内的每个数都加上 iii,增加后的 ∑j=1naj2\sum\limits_{j=1}^n a_j^2j=1naj2 最大是多少。询问相互独立,即每次询问时给每个数加的值不保留到下一次询问。

例如,对于序列 {−3,1,2,2}\{-3,1,2,2\}{3,1,2,2},若 m=5m=5m=5,则一种分段方式是 [−3][][1,2][][2][-3][][1,2][][2][3][][1,2][][2],增加后的序列是 −2,4,5,7-2,4,5,72,4,5,7,此时 ∑j=1naj2=94\sum\limits_{j=1}^n a_j^2=94j=1naj2=94

m=im=im=i 时的答案(即此时最大的 ∑j=1naj2\sum\limits_{j=1}^n a_j^2j=1naj2)为 qiq_iqi,出于良心考虑,你只需要输出 (∑i=1kqi) mod 998244353\left(\sum\limits_{i=1}^k q_i\right) \bmod 998244353(i=1kqi)mod998244353 即可。标准程序不基于特殊的输出方式,即能独立求出每一个 qiq_iqi

输入格式

第一行两个正整数 n,kn,kn,k,同题意。

接下来一行 nnn 个整数,表示 {an}\{a_n\}{an}

输出格式

一行一个整数,表示 (∑i=1kqi) mod 998244353\left(\sum\limits_{i=1}^k q_i\right) \bmod 998244353(i=1kqi)mod998244353

输入输出样例 #1

输入 #1

4 3
-3 1 2 2

输出 #1

141

说明/提示

【样例解释】

m=1m=1m=1 时,最优策略是 [−3,1,2,2][-3,1,2,2][3,1,2,2]q1=(−2)2+22+32+32=26q_1=(-2)^2+2^2+3^2+3^2=26q1=(2)2+22+32+32=26

m=2m=2m=2 时,最优策略是 [−3][1,2,2][-3][1,2,2][3][1,2,2]q2=(−2)2+32+42+42=45q_2=(-2)^2+3^2+4^2+4^2=45q2=(2)2+32+42+42=45

m=3m=3m=3 时,最优策略是 [−3][][1,2,2][-3][][1,2,2][3][][1,2,2]q3=(−2)2+42+52+52=70q_3=(-2)^2+4^2+5^2+5^2=70q3=(2)2+42+52+52=70

(∑i=1kqi) mod 998244353=(q1+q2+q3) mod 998244353=(26+45+70) mod 998244353=141\left(\sum\limits_{i=1}^k q_i\right) \bmod 998244353=(q_1+q_2+q_3)\bmod 998244353=(26+45+70)\bmod 998244353=141(i=1kqi)mod998244353=(q1+q2+q3)mod998244353=(26+45+70)mod998244353=141

【数据范围与约束】
测试点编号 分数 n≤n\leqn k≤k\leqk ∣ai∣≤\lvert a_i\rvert \leqai 特殊性质
1∼31\sim 313 151515 121212 121212 100010001000
4∼64\sim 646 151515 100010001000 100010001000 100010001000
7∼87\sim 878 101010 10610^6106 10610^6106 10710^7107 ai≥0a_i\geq0ai0
9∼129 \sim 12912 202020 10610^6106 100010001000 10710^7107
13∼2013\sim 201320 404040 10610^6106 10710^7107 10710^7107

C++实现

#include<bits/stdc++.h>
#define XD 114514

using namespace std;
int n,k;
const int mod=998244353;
long long a[1000010],ans;
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	} 
	for(int i=1;i<=k;i++){
		for(int j=1;j<=n;j++){
			if(abs(a[j]+1)>abs(a[j]+i)){//判断放最左面还是最右面
				ans+=(a[j]+1)*(a[j]+1);
				ans%=mod;
			}else{
				ans+=(a[j]+i)*(a[j]+i);
				ans%=mod;
			}
		}
	}
	cout<<ans;
	return 0;
}

在这里插入图片描述

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

更多推荐