ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 【2020普专提十连测Day7刷题赛】蜂国建设者

2020-11-21 18:35:11  阅读:223  来源: 互联网

标签:min 提十连测 题解 cal long leq 2020 lim --


【2020普专提十连测Day7刷题赛】蜂国建设者

10pts

只有 \(9\) 种情况,手玩打表即可

20pts

设所有子六边形个数为 \(ans1\) ,面积之和为 \(ans2\) ,显然 \(ans=\frac{ans2}{ans1}\)

暴力枚举

Task 5 30pts

为方便叙述,本题解中使用 包含的单元格\(-1\) 表示边的长度,即为题目中所述边长 \(-1\)

这种性质下只有形如 \((1,1,x)\) 的子六边形,其面积为 \(3x+4\)

把每个子六边形简化成“中心线”上的一条线段

于是转化到了一维的情况,这个与这道题的简化版 讨论 方法是一样的

\(ans1\) :枚举端点,$ ans1=\sum\limits_{i=1}^{c}(c-i+1) = c^2-\frac{c(c+1)}{2}+c = \frac{c(c+1)}{2} $

\(ans2\) :枚举长度,$ ans2=\sum\limits_{i=1}^{c}(c-i+1)(3i+4)$

\(O(c)\) 已经可以轻松通过了

\(ans2\) 的式子可以进一步化开 \(O(1)\) 计算,具体可以参照 讨论 ,这里不过多赘述。最后得到的是 \(ans=c+5\)

结合以上方法可得到 \(40-50pts\)

#include<bits/stdc++.h>
using namespace std;
long long a,b,c;
int main(){
	scanf("%lld%lld%lld",&a,&b,&c);
	printf("%.3lf",1.0*(c+5));
}

6行代码就有 30pts​ ,是不是很良心

60pts

先固定三边 \(a\), \(b\), \(c\) ,考虑枚举每种子六边形对应的三边 \(i\), \(j\), \(k\),计算个数

记边 \(x\) 的对边为 \(x'\) ,比如 \(a\) 的对边就是 \(a'\)

有一种想法是 \(i \leq a\) , \(j \leq b\), \(k \leq c\) ,这显然是错误的,以下是反例

显然正确的是 \(i+j \leq a+b\) , \(i+k \leq a+c\), \(j+k \leq b+c\) (可以补成等边三角形),因此 \(i\), \(j\), \(k\) 的范围不会太大,保证枚举的时间复杂度为 \(O(abc)\)

考虑如何计算一种大小的子六边形的个数 \(cal(i,j,k)\)

首先将它 \(j\) 和 \(k\) 交点放在 \(b\) 和 \(c\) 交点,显然当 \(a \leq b \leq c\) 时是做得到的

考虑一步一步向下移,每一步计算向左下和右下分别能走 \(l\) 和 \(r\) 步

模拟一下发现,前半段 \(l\) 和 \(r\) 是不变的,而后半段它们逐渐减小,直到有一个变为 \(0\)

\(l\) 和 \(r\) 是等价的,先只考虑 \(l\) ,假设移动了 \(t\) 步

记 \(i\) 向左下移动到直线 \(a\) 的距离为 \(b-j\),

\(k'\) 向下移动到直线 \(c'\) 的距离为 \(a+b-i-j-t\)

显然 \(l=min(b-j,a+b-i-j-t)\)

同理 \(r=min(c-k,a+c-i-k-t)\)

再来考虑 \(t\) 的最大值,即是 **\(k'\) 向下移动到直线 \(c'\) 的距离 \(a+b-i-j\) **和 **\(j'\) 向下移动到直线 \(b'\) 的距离 \(a+c-i-k\) **的最小值

注意到自身的状态也要算,故

\(cal(i,j,k)=\sum\limits_{t=0}^{min(a+b-i-j,a+c-i-k)}(min(b-j,a+b-i-j-t)+min(c-k,a+c-i-k-t)+1)\)

需要注意负数, \(b-j \geq 0\) , $ c-k \geq 0$ ,可以直接在枚举时剪枝优化(优化 \(1\) )

前面提到 \(i+j \leq a+b\) , \(i+k \leq a+c\), \(j+k \leq b+c\)

固定 \(i\) 的范围,就可以枚举 \(j \leq a+b-i\) , \(k \leq a+c-i\) (优化 \(2\) )

至于计算 \(ans2\) ,分割可知每个子六边形的面积为 \(S(i,j,k)=i(j+1)+j(k+1)+k(i+1)+1\)

时间复杂度 \(O((abc)^2)\)

常数小,可以通过 \(Task \ 1,2,3,5 +Task \ 4_1\) \(75pts\)

还要注意只有当 \(a \leq b \leq c\) 时才能这样做,否则会出现这种情况

3

显然 \(ans(a,b,c)=ans(a,c,b)\) ,在开始时需要将 \(a,b,c\) 从小到大排序,否则只有 \(50 pts\)

#include<bits/stdc++.h>
using namespace std;
long long a,b,c;
long long ans1,ans2;
long long cal(long long i,long long j,long long k){
	long long ans=0;
	long long x=a+b-i-j;
	long long y=a+c-i-k;
	while(x>=0 && y>=0){
		ans+=min(x,b-j)+min(y,c-k)+1;
		x--;y--;
	}
	return ans;
}
int main(){
	scanf("%lld%lld%lld",&a,&b,&c);
	if(a>b) swap(a,b);if(b>c) swap(b,c);if(a>b) swap(a,b);
	a--,b--,c--;
	for(long long i=1;i<=a+min(b,c);i++)
		for(long long j=1;j<=min(b,a+b-i);j++)
			for(long long k=1;k<=min(c,a+c-i);k++){
				long long t=cal(i,j,k);
				ans1+=t;
				ans2+=t*(i*(j+1)+j*(k+1)+k*(i+1)+1);
			}
	printf("%.3lf",1.0*ans2/ans1);
}

85-100pts

考虑优化 \(cal(i,j,k)\)

前提还是有 \(b-j \geq 0\) , $ c-k \geq 0$ ; \(i+j \leq a+b\) , \(i+k \leq a+c\), \(j+k \leq b+c\)

令 \(lim=min(a+b-i-j,a+c-i-k)\)

\(cal(i,j,k)\)

\(=\sum\limits_{t=0}^{lim}(min(b-j,a+b-i-j-t)+min(c-k,a+c-i-k-t)+1)\)

\(=\sum\limits_{t=0}^{lim}(min(0,a-i-t)+b-j+min(0,a-i-t)+c-k+1)\)

\(=2\sum\limits_{t=0}^{lim}min(0,a-i-t)+(b-j+c-k+1)(lim+1)\)

现在只考虑前面那部分,当 \(t \leq a-i\) 时为 \(0\) ,否则为 \(a-i-t\) ,再令 \(d=max(0,a-i+1)\) ,所以

\(cal(i,j,k)=2\sum\limits_{t=d}^{lim}(a-i-t)+(b-j+c-k+1)(lim+1)\)

若 \(d>lim\) ,则 \(cal(i,j,k)=(b-j+c-k+1)(lim+1)\)

否则,

\(cal(i,j,k)\)

\(=-2\sum\limits_{t=d}^{lim}t+2(a-i)(lim-d+1)+(b-j+c-k+1)(lim+1)\)

\(=-(d+lim)(lim-d+1)+2(a-i)(lim-d+1)+(b-j+c-k+1)(lim+1)\)

\(=(2a-2i-d-lim)(lim-d+1)+(b-j+c-k+1)(lim+1)\)

这个式子已经可以 \(O(1)\) 计算出 \(cal(i,j,k)\) 了

还可以把 \(cal\) 直接搬到主函数来

时间复杂度 \(O(abc)\)

已经可以通过本题

不优化只能得到 \(85pts\)

#include<bits/stdc++.h>
using namespace std;
long long a,b,c;
long long ans1,ans2;
int main(){
	scanf("%lld%lld%lld",&a,&b,&c);
	a--,b--,c--;
	if(a>b) swap(a,b);if(b>c) swap(b,c);if(a>b) swap(a,b);
	for(long long i=1;i<=a+min(b,c);i++){
		for(long long j=1;j<=min(b,a+b-i);j++){
			for(long long k=1;k<=min(c,a+c-i);k++){
				long long t=0;
				long long lim=min(a+b-i-j,a+c-i-k);
				long long d=max(0LL,a-i+1);
				if(d<=lim) t=(lim-d+1)*(2*a-2*i-d-lim);
				t+=(b-j+c-k+1)*(min(a+b-i-j,a+c-i-k)+1);
				ans1+=t;
				ans2+=t*(i*(j+1)+j*(k+1)+k*(i+1)+1);
			}
		}
	}
	printf("%.3lf",1.0*ans2/ans1);
}

标签:min,提十连测,题解,cal,long,leq,2020,lim,--
来源: https://www.cnblogs.com/Appleblue17/p/14016643.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有