嚯嚯嚯杨守凯天保

P1982 [NOIP2013 普及组] 小朋友的数字

/\* 这道题前50%的数据满足n<=1000,O(n^2)的算法就可以搞定 但100%的数据满足n<=1000000,需要O(n)的算法。所以考虑前缀和。 \*/ ```cpp #include<bits/stdc++.h> using namespace std; long long n,p,num[1000010],a[1000010],b[1000010],s[1000010],t1,t2; int main(){ scanf("%lld%lld%lld",&n,&p,&num[1]); a[1]=b[1]=num[1]; for(int i=2;i<=n;i++){ scanf("%lld",&num[i]); num[i]+=num[i-1]; a[i]=max(num[i]-num[i-1],a[i-1]+num[i]-num[i-1]);//包含小朋友i的最大连续数字和 b[i]=max(b[i-1],a[i]);}//小朋友i及其之前的连续若干个数字之和的最大值(即特征值) s[1]=b[1];s[2]=(s[1]+b[1]); t1=b[1]/p;s[1]%=p; for(int i=3;i<=n;i++){ s[i]=max(s[i-1],s[i-1]+b[i-1]); t2+=s[i]/p; s[i]%=p; } if(t1>t2||(t1==t2&&s[1]>=s[n]))printf("%lld\n",s[1]);//jsz大佬出来解释这一句!!! 看不懂!!! else printf("%lld\n",s[n]); return 0; } ```
by qscweadzx @ 2017-10-22 21:27:56


因为题目里面的第一个小盆友的特征值和分数就是它自己的数字,和后面其他小盆友的不同,所以应该输出s1和sn中的较大者。而我们在前面计算的时候就已经直接取模了,根据余数无法判断出两数原数的大小,所以我们每取一次余数,就将去掉的这几个p的个数都给保存着,所以真实的未取模的s1值应该是p\*t1+s1,s2值应是p\*t2+s2,而s1和s2都是不到p的,所以我们先比较两者p的个数t1和t2(这就相当于我们两数比大小先比较最高位,可以将这两个数看作是两个两位数,p进制的)
by jszjinshengzhi @ 2017-10-22 21:53:25


@[jszjinshengzhi](/space/show?uid=48343) 谢谢
by _Felix @ 2019-10-29 07:24:30


|