南沙C++信奧賽陳老師解一本通題: 1963:【13NOIP普及組】小朋友的數字

南沙区信奥赛陈老师發表於2024-10-01

【題目描述】

有 nn 個小朋友排成一列。每個小朋友手上都有一個數字,這個數字可正可負。規定每個小朋友的特徵值等於排在他前面(包括他本人)的小朋友中連續若干個(最少有一個)小朋友手上的數字之和的最大值。

作為這些小朋友的老師,你需要給每個小朋友一個分數,分數是這樣規定的:第一個小朋友的分數是他的特徵值,其它小朋友的分數為排在他前面的所有小朋友中(不包括他本人),小朋友分數加上其特徵值的最大值。

請計算所有小朋友分數的最大值,輸出時保持最大值的符號,將其絕對值對 p 取模後輸出。

【輸入】

第一行包含兩個正整數 n、p,之間用一個空格隔開。

第二行包含 nn 個數,每兩個整數之間用一個空格隔開,表示每個小朋友手上的數字。

【輸出】

輸出只有一行,包含一個整數,表示最大分數對 pp 取模的結果。

【輸入樣例】

5 997
1 2 3 4 5

【輸出樣例】

21

【提示】

【輸入輸出樣例說明】

小朋友的特徵值分別為1、3、6、10、15,分數分別為1、2、5、11、21,小朋友的特徵值分別為對 997 的模是 21。

【輸入輸出樣例 2】

輸入:

5 7
-1 -1 -1 -1 -1

輸出:

-1

【輸入輸出樣例說明】

小朋友的特徵值分別為−1、−1、−1、−1、−1,分數分別為−1、−2、−2、−2、−2,最大值−1−1 對 77 的模為−1−1,輸出−1。

【資料範圍】

對於 50%的資料,1≤n≤1,000,1≤p≤1,000 所有數字的絕對值不超過 1000;

對於 100%的資料,1≤n≤1,000,000,1≤p≤109,其他數字的絕對值均不超過 109。

#include <bits/stdc++.h>
using namespace std;
long long  dp[1000001],a[1000001]; //dp求最大連續欄位和 dp[i]以i結束的最長連續欄位和 
long long score[1000001],feature[1000001];	//分數 和特徵值先求出 
int main()
{
	long long n,p,ans=1e-10;
	cin>>n>>p;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		dp[i]=a[i];
	}	
	for(int i=1;i<=n;i++)
		dp[i]=max(dp[i],dp[i-1]+a[i]);		
	long long maxv=feature[1]=dp[1];
	for(int i=2;i<=n;i++)
	{
		maxv=max(dp[i],maxv);
		feature[i]=maxv;
	}	
  	score[1]=feature[1]%p;
  	score[2]=( score[1]+feature[1] )%p;
	for(int i=3;i<=n;i++)
		score[i]=max(score[i-1], score[i-1]+feature[i-1]  )%p;
	if(score[1] > 0)  //如果第一個分數大於0,最後個一定是最大的 
		ans = score[n];  
   	else
	    ans = max(score[1], score[n]);// 如果第一個小於0,則要比較第1個跟最後一個 
	cout<<ans;
	return 0;
}
南沙C++信奧賽陳老師解一本通題: 1963:【13NOIP普及組】小朋友的數字

相關文章