1 solutions
-
1
这个题可以通过找数学规律的思想,分别计算出前L-1项的和前R项的,利用前缀和思想相减即可得出答案。
此外,这道题如果直接暴力,可以获得36%的分数,使用普通的前缀和优化(就是使用前缀和分别计算前L-1和前R天所完成的工作总量,相减就能得到[L,R]时间内完成的工作量),可以获得72%的分数。代码就不放了,有兴趣的同学可以自己尝试一下。
下面是这个题的正解,也就是开头所提出的正确做法: 通过观察,我们可以发现:学长所完成的工作量是单调递增的,正好是有连续n天完成的工作量是n,即有1天完成的工作量为1,有2天完成的工作量为2,有n天完成的工作量为n……于是,完成n项工作的最后一天恰好是1+2+……+n,即第n*(n+1)/2天。于是,我们便可以通过下面的公式得知第L-1天和第R天所完成的工作量。在公式中用ans表示,而n表示的则是在ans以内最大的可以完成n项工作的最后一天。
即:
这是一个一元二次方程组,我们可以使用初中的知识,解出这个方程即可。
由于正好是有连续n天完成的工作量是n,假设将每连续的n天分为1组,前n组的总工作量便是:
可以由立方和公式求出结果:
再利用
求出第(n+1)组中剩下的天数,每天乘上n+1,便可求出第1天到第ans天的总工作量G。用1到R的结果减去1到L-1的结果即可得出答案~
$$G={n*(n+1)*(2*n+1)\over6} +(ans-{n*(n+1)\over2})*(n+1) 【公式IV】 $$代码如下:
#include<bits/stdc++.h> using namespace std; long long func(long long s) { long long n,ans,P; double a=1,b=1,c=-(2*s); double N=(-b+sqrt(b*b-4*a*c))/(2*a);//公式I n=(long long)N; P=(1+n)*n/2; ans=(s-P)*(n+1)+n*(n+1)*(2*n+1)/6;//公式IV,s-p为公式III,之后为公式II,加起来求和即可 return ans; } int main() { int q; scanf("%d",&q); while(q--) { long long l,r; long long ansl=0,ansr=0; scanf("%lld %lld",&l,&r); ansl=func(l-1); ansr=func(r);//求L-1和R long long ans=ansr-ansl; printf("%lld\n",ans); } return 0; }
Information
- ID
- 6685
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 9
- Tags
- # Submissions
- 214
- Accepted
- 12
- Uploaded By