9.14 砍树题解

  这道题讲真还是挺友好的,纯暴力拿了50分。

  当时我选择第一道题去搞他,第一反应是二分答案,毕竟理论上每次考试都有一道水题,然而仔细想想便可知不靠谱,然后就打了一个倒着搜的暴力,懵逼到结束。

  这道题当时预测是一道数学题,然而看完题解发现,貌似是乱搞……我反正是不知道如何归类了。

  假设我们已经知道当前的d,那么我们的答案也就出来了:

   num=∑(┍a[i]/d┑*d-a[i])

  那么只要num<=k就一定成立了,那么我们令sum=k+∑a[i]

  那么我们会得到一个有趣的式子∑┍a[i]/d┑*d<=sum显然,┍a[i]/d┑是一个递减的分段函数,那么我们把它除过去,便可以知道当前d的最大可行取值。那么如何去找函数的每一段呢?我们设函数左端点为l,右端点为r,r=sum/(sum/l),很神奇,但貌似不太好证,总之是对的。

  

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<queue>
 6 #include<algorithm>
 7 #include<cmath>
 8 #define N 105
 9 using namespace std;
10 long long n,m;
11 long long a[N];
12 long long sum,ans;
13 int main()
14 {
15     scanf("%lld%lld",&n,&m);
16     for(int i=1;i<=n;i++)
17     {
18         scanf("%lld",&a[i]);
19         sum+=a[i];
20     }
21     sum+=m;
22     long long d=0;
23     while(1)
24     {
25         if(sum/(d+1)<=0)break;
26         d=sum/(sum/(d+1));
27         long long an=0;
28         for(int i=1;i<=n;i++)
29         {
30             long long tt=a[i]/d;
31             if(a[i]%d) tt++;
32             an+=tt*d;
33         }
34         if(an<=sum) ans=d;
35     }
36     printf("%lld\n",ans);
37     return 0;
38 }
View Code

 

转载于:https://www.cnblogs.com/liutianrui/p/7528352.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值