幼い頃からC++を学びましょう!CSP-J 試験準備の学習プロセスにおける質問を記録し、あらゆる瞬間を記録します。
まとめ記事を添付します: CSP-J準決勝スプリント必須回答問題 | まとめ_プログラミング大好きコミュニケーターのブログ - CSDN Blog
[タイトル説明]
n 人の子供たちが一列に並んでいます 。すべての子供は手に数字を持っており、この数字は正または負の場合があります。各子供の特性値は、目の前の子供(自分を含む)のうち連続する数人(少なくとも一人)の子供の手の数字の合計の最大値に等しいと規定されています。
これらの子供たちの教師として、あなたは各子供に得点を与える必要があります。得点は次のように規定されています: 最初の子供の得点はその子供の特性値であり、他の子供の得点はその前の子供全員の得点です。彼 (彼を除く)、私)、子供のスコアにその固有値の最大値を加えたもの。
すべての子のスコアの最大値を計算し、出力時に最大値の符号を保持し、その絶対値を法 pで出力してください 。
【入力】
最初の行には、 スペースで区切られた2 つの正の整数nとpが含まれています。
2 行目には n 個の 数字が含まれており、各 2 つの整数はスペースで区切られており、各子供の手の番号を示しています。
【出力】
p を法とする最大スコアを表す整数 。
【入力サンプル】
5 997
1 2 3 4 5
【出力サンプル】
21
【詳しいコード説明】
#include <bits/stdc++.h>
using namespace std;
int n, p;
long long sum, maxv, ans;
long long a[1000005], b[1000005]; //a[]特征值,b[]分数
int main()
{
cin >> n >> p;
sum = 0; //前面的数对后面值的贡献,小于0时赋值为0
maxv = -1e9;
for (int i=1; i<=n; i++) {
int x;
cin >> x;
sum += x;
maxv = max(maxv, sum);
a[i] = maxv; //非严格单调递增序列
if (sum<0) sum=0;
}
b[1]=a[1];
b[2]=b[1]+a[1];
int flag=0;
for (int i=3; i<=n; i++) {
//b[i-1]表示a[1]+b[1],a[2]+b[2],...,a[i-2]+b[i-2]的最大值
b[i]=max(b[i-1]+a[i-1], b[i-1]);
if (b[i]>b[1]) {
flag=1;
b[i]%=p;
}
}
if (flag || n==2) ans = b[n]; //最后一个测试点数据是n==2时的特判
else ans = b[1]%p;
cout << ans;
return 0;
}
【運用結果】
2 7
3 5
6