买糖吃——题解

买糖吃

题目描述:

洋神带着他的小伙伴去买糖吃。

洋神想要一款特殊的糖果。柜台上的这种糖果是用一个圆圈穿起来的n颗糖果。每颗糖果有自己的美味值。商家会根据顾客的需求,从中选出连续x颗糖果卖给顾客。这串糖果的美味值是这x颗糖果美味值的平均值。

洋神的胃口不大,他希望他的糖果由[L,R]颗糖组成。而且他想要使得这串糖果的美味值最大。为了方便和小伙伴分享糖果,洋神希望这串糖果的个数是偶数。

看小数是一件麻烦的事情,请你用整数或者分数的形式,告诉洋神最大的美味值。

输入格式:

第一行,包含三个整数,n,L,R。

第二行,n个整数,代表每一颗糖果的美味值。

输出格式:

一个数,表示美味值ai。

样例输入:

5 3 4
3 1 2 4 5

样例输出:

7/2

提示:

1≤L≤R≤n≤10^5

0≤ai≤10^9

数据随机生成。

时间限制:1000ms
空间限制:256MByte

这就是那道坑害了我很久的题目,刚开始的时候连题目的意思都没有看懂,主要是他希望他的糖果由[L,R]颗糖果组成那个部分。其实就是说糖果的数量num,L<=num<=R,语文是真的不行。然后接下来贴一下刚开始自己写的爆零代码。

 

#include<bits/stdc++.h>
using namespace std;
double s;
int a[200001],le,ri,n,up,down,sum=0;
int main(){
	cin>>n>>le>>ri;
	for (int i=1; i<=n; i++){
		cin>>a[i];
		a[i+n]=a[i];
	}
	if (le%2==1) le++;
	for (int i=le; i<=ri; i+=2){
		s=-1;//对,就是这里。
		for (int l=1; l<=n; l++){
			sum=0;
			for (int k=1; k<=i; k++){
				sum+=a[l+k-1];
			}
			if (sum*1.0/i>s) {
				up=sum;
				down=i;
			s=sum*1.0/i*1.0;
			}
		}
	}
	int o=__gcd(up,down);
	if (down/o!=1)
	cout<<up/o<<"/"<<down/o;
	else cout<<up/o;
	return 0;
}

对就是那个地方,我只要把s=-1给放到那层for的外面就可以拿到五十分,我也不知道我那个时候怎么想的居然会把s=-1放到里面去。然后把代码改了一下(就是把s=-1放到外面,还有for的小小优化),发现比五十分只多了二十分

#include<bits/stdc++.h>
using namespace std;
double s;
int a[200001],le,ri,n,up,down,sum=0;
int main(){
	cin>>n>>le>>ri;
	for (int i=1; i<=n; i++){
		cin>>a[i];
		a[i+n]=a[i];
	}
	if (le%2==1) le++;	s=-1;
	for (int i=le; i<=ri && i<=2*le/*for的小小优化*/; i+=2){
	
		for (int l=1; l<=n; l++){
			sum=0;
			for (int k=1; k<=i; k++){
				sum+=a[l+k-1];
			}
			if (sum*1.0/i>s) {
				up=sum;
				down=i;
			s=sum*1.0/i*1.0;
			}
		}
	}
	int o=__gcd(up,down);
	if (down/o!=1)
	cout<<up/o<<"/"<<down/o;
	else cout<<up/o;
	return 0;
}

最后就要来说一下看起来逼格很高的前缀和,听学长讲这一题的时候就是一脸懵逼??前缀和?这是什么东西,后来经过我和同桌数学大佬的一番探讨发现其实就是求和!对没错就是放一个sum数组(程序里用的是num),用sum[i]来存前i个数的总和。这就是传说中的前缀和。用前缀和可以让程序跑得比之前快的原因,就是在刚开始的时候将每一个和值求出来,这样在后来的操作中只要将sum[k]-sum[l-1]就能得到在k到l这段区间内所有数字的和。这样就不用在程序中每次求连续n个数的和都要一次次地跑了,好,新技能get,接下来就是AC代码,其实和爆零代码的字数差距并不是很大

#include<bits/stdc++.h>
using namespace std;
double s;
int a[200001],le,ri,n,up,down,sum=0,num[200001]={0};
int main(){
	cin>>n>>le>>ri;
	for (int i=1; i<=n; i++){
		cin>>a[i];
		a[i+n]=a[i];
	}
	if (le%2==1) le++;	s=-1;
	num[1]=a[1];
	num[0]=0;
	for (int i=2; i<=n*2; i++) num[i]=num[i-1]+a[i];
	for (int i=le; i<=ri && i<=2*le; i+=2){
		for (int l=le; l<=2*n; l++){
			sum=num[l]-num[l-i];
			if (sum*1.0/i>s) {
				up=sum;
				down=i;
			s=sum*1.0/i*1.0;
			}
		}
	}
	int o=__gcd(up,down);
	if (down/o!=1)
	cout<<up/o<<"/"<<down/o;
	else cout<<up/o;
	return 0;
}

qwq,后来试了一下,只要有前缀和就算不用for里面的小小优化也是可以的。前缀和自己应该能够想到的啊,那个毒性极强的s=-1;放在for里面坑害的太深了,诶,不应该啊。。(qwq,html好难,多亏有同桌大佬)

made by cain-

posted @ 2017-08-03 15:02  |斗蜂|  阅读(336)  评论(0编辑  收藏  举报