洛谷P1982 小朋友的数字——题解

题目传送

简单地说,这题就是让我们求前i个数的最大子串和和最值。

对于最大子串和,我们可以设一个变量qian,表示以当前元素结尾的最大子串的子串和。若搜索完第i-1个小朋友,现在看到第i个小朋友时,若qian大于0,就说明以第i-1个小朋友为结尾的最大子串和的值大于0,那么让这小朋友连上这个字串的话得到的子串和一定比让这个小朋友独自一人组成一个子串得到的和要大,而且在这时第i个小朋友连上这个字串后得到的这个子串也是以第i个小朋友为结尾的和最大的子串;若qian小于0,那第i个小朋友就不如自己单独组成一个新的子串,这样得来的子串和还要比让这个小朋友连上之前的子串得到的子串和要大。若qian大于目前搜索到的所有子串的和中最大的和maxn还要大,就更细maxn。第i个小朋友的特征值就是此时的maxn(注意,以第i个小朋友为结尾的子串不一定是前i个小朋友中组成的所有子串中子串和最大的子串)。

对于最值,我们要每次求第i个小朋友的分数时都把前面的小朋友分数加特征值都扫一遍吗?不用。我们只要维护一个表示当前的前i-1个小朋友中最大的分数与特征值的和的变量maxx就行了。

根据题目范围,显然小朋友的“手牌值”和特征值都是在long long 类型以内的。对于分数也好像在long long 以内。但真的是这样吗?

我们使单位“1”等于109(即小朋友最大可能的手牌值),看一下数据最大的情况,即有1000000个小朋友,每个小朋友手里的牌值都是一个“单位‘1’”,列有下表:

小朋友编号123456789...1,000,000
手牌值(1:109111111111...1
特征值(1:109123456789...1,000,000
分数(1:10912471116222937...499999500001

499999500001*109=4.99999500001*1020,而long long的数据最大约9*1018,显然会爆,怎么办?这里是用两个long long 型high和low用1015进制表示一个数,即任意一个不超过题意数据范围内的数都可以用high*base+low表示(base=1015)。一个普通的数x转成这样一个数,只需high=x/base,low=x%base。相加的话注意进位就好。对于符号,我们只要保证high和low同号或high为0就行。同时发现,因为low的绝对值小于base,那么如果low为负数,加上一个base就变成正数了;如果low为正数,减去一个base就变成负数了。

见AC代码:

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cctype>
 5 
 6 using namespace std;
 7 
 8 long long spe[1000001],num[1000001],ans,mod,qian ;
 9  
10 const long long base=1000000000000000;
11  
12 char ch;
13 
14 bool f;
15 
16 inline long long read()
17 {
18     ans=0;
19     f=0;
20     ch=getchar();
21     while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
22     while(isdigit(ch)) ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
23     return f?-ans:ans;
24 }
25 
26 struct lll{
27     long long high,low;
28 }poi[1000001],maxx;
29 
30 inline lll operator+(lll a,const lll &b)
31 {
32     a.low+=b.low;
33     a.high+=b.high+a.low/base;
34     a.low%=base;
35     if(a.high>0&&a.low<0) a.high--,a.low+=base;
36     if(a.high<0&&a.low>0) a.high++,a.low-=base;
37     return a;
38 }
39 
40 inline lll operator+(lll a,const long long c)
41 {
42     lll b;
43     b.high=c/base;
44     b.low=c%base;
45     a.low+=b.low;
46     a.high+=b.high+a.low/base;
47     a.low%=base;
48     if(a.high>0&&a.low<0) a.high--,a.low+=base;
49     if(a.high<0&&a.low>0) a.high++,a.low-=base;
50     return a;
51 }
52 
53 inline lll max(lll a,lll b)
54 {
55     if(a.high>b.high) return a;
56     if(a.high<b.high) return b;
57     if(a.low>=b.low) return a;
58     else return b;
59 }
60 
61 int main()
62 {
63     int n=read(),mod=read();
64     for(int i=1;i<=n;i++) num[i]=read();
65     long long maxn=num[1];
66     for(int i=1;i<=n;i++)
67     {
68         if(qian<0) qian=0;
69         qian+=num[i];
70         maxn=max(maxn,qian);
71         spe[i]=maxn;
72     }
73     poi[1].low=spe[1]%base;
74     poi[1].high=spe[1]/base;
75     maxx=poi[1]+spe[1];
76     for(int i=2;i<=n;i++)
77     {
78         poi[i]=maxx;
79         maxx=max(poi[i]+spe[i],maxx);
80     }
81     maxx=poi[1];
82     for(int i=2;i<=n;i++)
83         maxx=max(maxx,poi[i]);
84     cout<<(base%mod*maxx.high+maxx.low)%mod;
85     return 0;
86 }

 

有人说难题都是一个个简单的题叠加成的。对于很多题,其实我们只要把它分解成一个个我们能解决的简单的子问题,最后合并一下就行了。

转载于:https://www.cnblogs.com/InductiveSorting-QYF/p/11049532.html

题目描述似乎缺失了关键信息,通常我会需要了解“P10780 食物”是什么具体的算法竞赛题目,它来自在线平台洛谷(Luogu),以及该题目的大致背景、条件和目标。洛谷食物(Food)可能是某种数据结构或算法问题,比如贪吃蛇、分配任务等。 然而,我可以给你提供一个通用的模板: **[洛谷 P10780 食物 - 题目解析]** 题目名称:P10780 食物(假设是关于食物分配或者饥饿游戏的问题) 链接:[插入实际题目链接] **背景:** 此题通常涉及动态规划或者搜索策略。场景可能是有n个参与者(选手或角色),每个都有特定的食物需求或者优先级,我们需要在有限的食物资源下合理分配。 **分析:** 1. **输入理解**:首先读入n个参与者的信息,包括每个人的需求量或优先级。 2. **状态定义**:可以定义dp[i][j]表示前i个人分配完成后剩余的食物能满足第j个人的最大程度。 3. **状态转移**:递式可能涉及到选择当前人分配最多食物的版本,然后更新剩余的食物数。 4. **边界条件**:如果剩余食物不足以满足某人的需求,则考虑无法分配给他;如果没有食物,状态值设为0。 5. **优化策略**:可能需要对状态数组进行滚动更新,以减少空间复杂度。 **代码示例(伪代码或部分关键代码片段):** ```python # 假设函数分配_food(demand, remaining)计算分配给一个人后剩余的食物 def solve(foods): dp = [[0 for _ in range(max_demand + 1)] for _ in range(n)] dp = foods[:] # 从第一个到最后一个参与者处理 for i in range(1, n): for j in range(1, max_demand + 1): if dp[i-1][j] > 0: dp[i][j] = max(dp[i][j], dp[i-1][j] - foods[i]) dp[i][j] = max(dp[i][j], distribute_food_to(i, dp[i-1][j])) return dp[n-1][max_demand] ``` **相关问题--:** 1. 这道题是如何运用动态规划的? 2. 如果有优先级限制,应该如何调整代码? 3. 怎样设计搜索策略来解决类似问题?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值