2019.06.29【NOIP提高组】模拟 A 组(自然对数)

这一次比赛做的不是很好。

T1:这一题我以为是一道结论题,所以WA20了。

正解是树形dp。我们可以简化一下题目:先把树变成一条链,然后在花费1代价把链变成环。

然后就可以设f[x][0/1]表示把x为根的子树变成一条链,x一定/不一定是端点的最小代价。

对于f[x][0],我们分类讨论x是直接连在某一个儿子上,还是连在一个非儿子的后代上,就可以得出方程:f[x][0]=min(sum+2*son,sum+f[y][0]-f[y][1]+2*(son-1))。其中y是x的儿子,sum=sigma(f[y][1]),son是x的儿子的个数。因为我们要f[x][0]最小,所以求出f[y][0]-f[y][1]的最小值即可。

对于f[x][1],首先塔肯定包含f[x][0]的所有情况。接着我们x不是端点的情况,那么必有两颗子树作为端点子树,枚举这两棵子树p、q,方程为f[x][1]=min(f[x][0],sum+(f[p][0]-f[p][1])+(f[q][0]-f[q][1])+2*(son-2))。

最终,ans=f[1][1]。

 

总结:这题没有发现结论错误是因为暴力能处理的数据太小了,不足以发现错误。以后如果暴力能处理的数据太小,那么就不要太相信对拍,要自己想清楚一点。

 

T2:从小到大枚举答案,然后暴力构造最终的异或结果。枚举原数,根据a^b=c等价与b^c=a来倒推出另外一个数,看一看是否可行。这虽然很暴力,但是时间复杂度是可以过的。

 

总结:异或具有可逆性,即a^b=c,c^b=a。可以通过枚举最终结果来倒推。

 

T3:很容易把题目转换成把n分解成若干个数,使得这几个数的最小公倍数最大,并求出方案。

然后我们可以再发现一个性质:分解出来的每一个数只含一个质因子,这对结果是没有影响的。比如分解出来的一个数x=p1^q1*p2^q1...pk^qk,那么把w拆成p1^q1,p2^q2,...,pk^qk共k个数,那么对最终结果是没有影响的。

然后我们就可以进行dp了。设f[i][j]表示前i个质因数构成的和为j的最大的最小公倍数。则f[i][j]=max(f[i-1][j-w]*w),其中w为p[i]的某个次幂。

但是还有一个问题:f的值可能会很大,这怎么处理呢?我们可以发现在这一题里我们只需要f之间的大小关系,所以我们可以用自然对数来处理。

对于自然对数e,任何正整数x都能表示成e^y,即x=e^y,y=log(x)。而对于两个正整数a、b,a=e^a1,b=e^b1,则a*b=e^(a1+b1),这样我们就可以把乘法变成加法了。

我们把f[i-1][j-w]*w变成f[i-1][j-w]+log(w),这并不影响它们之间的大小关系,这样就可以解决f的值太大的问题了。

注意:f要用double型。

 

总结:1、C++中求x的自然对数的幂直接调用log(x)即可,而要把指数转换成正整数可以用exp()。例:e^y=x,则log(x)=y,exp(y)=x。

2、log函数耗的时间很多,能预处理的就预处理。

3、自然对数在只涉及乘法运算且要解决数太大的问题时运用。

 

T4:首先预处理以每一个点为中点时,横向/纵向扩展最远扩展的距离。

然后n^3枚举左上角和长度,O(n)判断是否可行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值