首页 > 其他分享 >中二羊专题:栋栋吃糖果

中二羊专题:栋栋吃糖果

时间:2023-05-14 11:12:58浏览次数:55  
标签:md 中二羊 sum 栋栋 int 快乐 ans 糖果

U163898

题目

题目背景

栋栋参加比赛拿下了一等奖,老师奖励了很多糖果。

题目描述

一共有 \(m\) 种糖果,其中第i种糖果的数量为 \(m_i\) 。栋栋吃糖时会获得快乐值,并且他喜欢换着口味吃糖。当栋栋吃下第一个糖果时快乐值为 \(0\) ,接下来,每吃一个不同口味的糖果(与上一个糖不同),快乐值就会增加 \(5\) 点,而连续吃下 \(k\) 个相同口味的糖果,快乐值就会减少 \(3*(k-1)\) 点。栋栋已经下定决心要吃完所有的糖果。现在他想知道如何安排吃糖的顺序才能使快乐值最大。请你求出最大快乐值。

输入格式

输入分两行
第一行输入整数 \(m\)
第二行输入 \(m\) 个整数,分别表示每种糖果的数量 \(m_i\) 。

输出格式

输出栋栋能获得的最大快乐值

输入输出样例

样例1
输入1
3
3 1 1
输出1
20
样例2
输入2
3
4 1 1
输出2
17

说明/提示

对于\(100\%\)的数据,有\(1<m\le1000\) , \(1\le m_i≤10000\) , \(1<m\le1000\),\(1≤m_i≤10000\)。保证结果在int范围内。

题解

定义

此题是广义鸽巢原理的一道例题
先说一下什么是鸽巢原理:
定义:如果 \(k+1\) 个或更多个物体放入 \(k\) 个盒子,那么至少有一个盒子包含了 \(2\) 个或更多的物体。此定理也被称为狄利克雷抽屉原理。
但是此题用到的是广义鸽巢原理。
定义:如果 \(N\) 个物体放入 \(k\) 个盒子,那么至少有一个盒子包含了至少 \(\left\lceil\dfrac{N}{k}\right\rceil\) 个物体。
举个例子,在100人中,至少有 \(\left\lceil\dfrac{100}{12}\right\rceil=9\) 个人的生日在同一个月。


看完题后,我们会发现,有许多东西我们都不需要。我们现在需要的是 \(N\) 和 \(k\) 。
用总糖果数量减去最大数量糖果类型可以得出其它糖果数量综合。
所以处理情况是这样的:

...
signed main(){
	int m,md=0,ans=0,sum,a;
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		scanf("%d",&a);
		ans+=a;
		md=max(md,a);
	}
	ans-=md;
	...
	return 0;
}

当我们发现吃糖时不用减少快乐值时,即吃重复糖最多只吃一次时:

...
	if(ans-md>=-1){
		printf("%d",(ans+md-1)*5);
		return 0;
	}
...

当我们发现必须减少快乐值时:
如果不计损失的快乐值,那么就只有 \(ans*10\) 的快乐值了。
我们可以这么理解:
我们已经知道了其它类糖果总数量为 \(ans\) ,最大数量糖果类总数量为\(md\) ,所以我们把可以看作有 \(md-1\) 个盒子要放下 \(ans\) 个糖果。(关键思路)
所以代码就出来了,如果求总和会要用到等差数列公式: \(\frac{n(a+n)}{2}\) 。(注意此处等差数列公式是 \(1+2+...+n-1+n\) )

...
	const int P1=ceil(md/(double)(ans+1));
	const int P2=md/(ans+1);
	const int P3=md%(ans+1);
	sum-=3*((ans+1-P3)*(P2-1)*P2/2+P3*P1*(P1-1)/2);
	printf("%d",sum);
...

代码(不建议看)

#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstdio>
using std::max;
signed main(){
	int m,md(0),ans(0),sum,a;
	scanf("%d",&m);
	for(register int i(1);i<=m;i=-~i){scanf("%d",&a);md=max(md,a),ans+=a;}
	ans-=md;
	if(ans-md>=-1){
		printf("%d",(ans+md-1)*5);
		exit(0);
	}
	sum=ans*10;
	const int P1=ceil(md/(double)(ans+1));
	const int P2=md/(ans+1);
	const int P3=md%(ans+1);
	sum-=3*((ans+1-P3)*(P2-1)*P2/2+P3*P1*(P1-1)/2);
	printf("%d",sum);
	exit(0);
	return 0;
}

后记:几年前的东西,看个乐子。

标签:md,中二羊,sum,栋栋,int,快乐,ans,糖果
From: https://www.cnblogs.com/SHOJYS/p/17398920.html

相关文章

  • 分糖果
    问题描述10个小孩围成一圈分糖果,老师分给第1个小孩10块,第2个小孩2块,第3个小孩8块,第4个小孩22块,第5个小孩16块,第6个小孩4块,第7个小孩10块,第8个小孩6块,第9个小孩14块,第10个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩;糖块数为奇数的人可向老师要一块。问经过这样几......
  • 135. 分发糖果
    老师想给孩子们分发糖果,有N个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。你需要按照以下要求,帮助老师给这些孩子分发糖果:每个孩子至少分配到1个糖果。相邻的孩子中,评分高的孩子必须获得更多的糖果。那么这样下来,老师至少需要准备多少颗糖果呢?示例1:......
  • 2.3 分糖果(补5月6日)
    #include<stdio.h>voidprint(ints[]);intjudge(intc[]);intj-0;/*记录糖果分配次数*/main()intsweet[10]={10,2,8,22,16,4,10,6,14,20};1*初始化数组数据*/inti,t[10],1;printf("child12345678910\n");printf("...................................
  • 分糖果
    一、问题描述:10个小孩围成一圈分糖果,老师分给第1个小孩10块,第2个小孩2块,第3个小孩8块,第4个小孩22块,第5个小孩16块第6个小孩4块,第7个小孩10块,第8个小孩6块,第9个小孩14块,第10个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩:糖块数为奇数的人可向老师要一块。问经过......
  • AcWing 4086 分糖果
    关于这道题我当时大意了https://www.acwing.com/problem/content/description/4089/关于我的某个变量没有初始化这件事,唯一想法,敲死得了,谁懂?其实就是一道简简单单的数学分析题,和大佬们不一样,萌新只会简简单单的小学数学(本人初二!)分析走起! 一道典型的数学问题() 虽然我WA了,......
  • 分糖果
    1.问题描述:10个小孩围成一圈分糖果,老师分给第1个小孩10块,第2个小孩2块,第3个小孩8块,第4个小孩22块,第5个小孩16块第6个小孩4块,第7个小孩10块,第8个小孩6块,第9个小孩14块,第10个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩:糖块数为奇数的人可向老师要一块。问经过这......
  • 分糖果
    一、问题描述:  10个小孩围成- -圈分糖果, 老师分给第1个小孩10块,第2个小孩2块,第3个小孩8块,第4个小孩22块,第5个小孩16块,第6个小孩4块,第7个小孩10块,第8个小孩6块,第9个小孩14块,第10个小孩20块。然后所有的小孩同时将手中的糖分一半给右边的小孩:糖块数为奇数的人可向老师要一块......
  • 分糖果
     分析:定义长度为10的整型数组来存储每人的糖果,定义一个while循环,while循环的条件是每个孩子手中的糖果不同,在while循环中再定义一个for循环,这个for循环用来计算给其他孩子分糖果,再定义一个for循环,这个for循环用来加上分到的糖果,其中数组的0号位特殊处理,定义一个函数judge来判断......
  • 13.糖果问题
       代码1实现:#include<stdio.h>intjudge(intsw[]);//判断每个孩子的手中糖果是否一致voidprint(intc[]);//打印每个孩子手里的糖果数intj=0;//记录分配的次数intmain(intargc,constchar*argv[]){intsweet[10]={10,2,8,22,16,4,10,6,14,20};intt[10];pri......
  • 分糖果
    #include<stdio.h>intj=0;intjudge(intsweet[]){ inti; for(i=0;i<10;i++) { if(sweet[0]!=sweet[i])return1; } return0;}voidprint(intsweet[]){ intk; printf("%2d",j++); for(k=0;k<10;k++) pr......