• 买糖吃——题解


    买糖吃

    题目描述:

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

    洋神想要一款特殊的糖果。柜台上的这种糖果是用一个圆圈穿起来的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-

  • 相关阅读:
    Redis在Windows上使用和集群配置
    Lzma(7-zip)和zlib
    Windump教程-参数介绍
    Windows 使用windump进行循环抓包
    wireshark长时间抓包分多个文件
    发现TCP的一种错误----客户端连接失败(10055错误号)
    MySQL [Err] 1055
    解决socket交互的10048和10055错误的总结
    Socket调用Close后如何终止套接口的问题
    linux下recv 、send阻塞、非阻塞区别和用法
  • 原文地址:https://www.cnblogs.com/cain-/p/7279791.html
Copyright © 2020-2023  润新知