1 solutions

  • 0
    @ 2024-6-11 17:38:03

    模拟题(80pts)

    • 从前往后预处理子段和最大值(特征值),根据题目描述处理每个同学的分值
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=1000010;
    int n,p;
    LL f[N]; //f[i]表示特征值 
    int main()
    {
        cin>>n>>p;
        LL s=0,maxs=-2e18;
        for(int i=1;i<=n;i++)
        {
            int x;
            cin>>x;
            s=max(s,0ll)+x; //连续子段和
            maxs=max(maxs,s); //最大子段和
            f[i]=maxs; //记录前i个数的最大连续子段和
        }
        LL res=f[1]; //第一个小朋友的分数 
    	LL score=2*f[1]; //第一个小朋友的分数+第一个小朋友的特征值(第二个小朋友的分数)
        for(int i=2;i<=n;i++) //枚举第i个人的分数
        {
            res=max(res,score); //更新前i个人的分数+特征值的最大值
            score=max(score,f[i]+score); //更新第i+1个人的分数
        }
        cout<<res%p; //输出分数最大值 
        return 0;
    }
    

    模拟题+高精度(100pts)

    • 由于f[i]f[i]做大可以到101510^{15},那么f[i]f[i]累加值会超过long long ,我们可以用一个a[0]a[0]表示第1818位,a[1]a[1]表示高1818位。
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=1000010;
    const LL B=1e15;
    int n,p;
    LL f[N];
    int main()
    {
    	cin>>n>>p;
    	LL s=0,maxs=-2e18; //最大子段和
    	for(int i=1;i<=n;i++)
    	{
    		int x;
    		cin>>x;
    		s=max(s,0ll)+x; //更新以当前数结尾的和
    		maxs=max(maxs,s); //更新最大子段和
    		f[i]=maxs;  //更新1到i的最大子段和
    	}
    	LL res[2]={f[1]}; //第一个分数
    	LL score[2]={f[1]*2}; //第二个人的分数(特征值+分数)
    	//因为f[i]的值可能到大10^15,那么f[i]累加会超过long  long,那么我们用 a[0]表示低18位,a[1]表示高18位
    	for(int i=2;i<=n;i++)
    	{
    		if(res[1]<score[1]||res[1]==score[1]&&res[0]<score[0]) //更新前i个人的最大分数
    		{
    			res[0]=score[0],res[1]=score[1];
    		}
    		if(f[i]>0) //有特征值可以增加分数
    		{
    			score[0]+=f[i];
    			score[1]+=score[0]/B;
    			score[0]%=B;
    		}
    	}
    	cout<<(res[1]*(B%p)+res[0])%p;
    	return 0;
    }
    
    • 1

    Information

    ID
    443
    Time
    1000ms
    Memory
    128MiB
    Difficulty
    10
    Tags
    # Submissions
    4
    Accepted
    2
    Uploaded By