【CodeForces 830C】奇怪的降复杂度
 
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=60638239
description
有n棵竹子,初始时每棵竹子高度都是0,每棵竹子每天长高1m
对于每棵竹子,我们不希望其高度超过a[i],如果超过了,我们就会把超过的部分减去
奇怪的是减去之后竹子就不会再长了
我们不希望每天去看一下竹子的情况,希望每隔d天去看一下竹子的情况
本着爱护环境的原则,我们不希望减去的竹子长度之和大于K
我们最多可以隔多少天去看一次竹子?
input
第一行两个整数n,K
第二行n隔整数表示a[i]
output
一个整数表示答案,即最大的d值
hint
20%:ai<=5*10^5
另有20%:k<=1
100%:1<=n<=100,0<=k<=10^11,1<=ai<=10^9
这道题我还愣是问大佬问了好久才搞懂。 
第一眼:而不是二分嘛,水!结果考试快结束是才反应过来这答案并不满足二分的性质。如:4  4   4,d选4比选3优。
那么怎么办呢? 
首先可以明确,d一定小于a[i]的最大值。那么这个d就太多了啊。如果直接暴力去for d,肯定是不行的,只能得20分。我们希望可以减少一些无用的d的枚举。
先可以得到公式: 
 
转化一下: 
 
我们可以发现,对于[ai/d]向上取整,有多个d对应相同的值。如:10/d,d=5,6,7,8,9都对应一个值2,可以证明d的数量是o(√n)
我们记录每一个ai对应的d,其中d可以代表一系列d。在算出了sigma([ai/d])后,可以根据上面的公式求出最大的d
暴力枚举得出的d,复杂度o(n*ai^0.5)
详情看代码吧。。。解释起来好麻烦。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=105;
const int M=100000+5;
ll a[N],n,k,c=0;
ll ans=0,tot=0,vec[N*M],cnt=0;
int main(){
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        c+=a[i];
        for(int j=1;j*j<=a[i];j++)
            vec[++cnt]=j,vec[++cnt]=(a[i]-1)/j+1;
    }
    c+=k;
    sort(vec+1,vec+cnt+1);
    cnt=unique(vec+1,vec+cnt+1)-(vec+1);
    for(int i=1;i<=cnt;i++){
        ll d=vec[i];
        tot=0;
        for(int j=1;j<=n;j++)
            tot+=(a[j]-1)/d+1;
        if(c/tot<d) continue;
        ans=max(ans,c/tot);
    }
    printf("%lld",ans);
    return 0;
}
总结: 
1、在想二分时可以举例子来验证答案的单调性 
2、把公式写出来时,可以结合一些数论的知识,看看能不能化简
【CodeForces 830C】奇怪的降复杂度的更多相关文章
- 暴力+降复杂度 BestCoder Round #39 1002 Mutiple
		
题目传送门 /* 设一个b[]来保存每一个a[]的质因数的id,从后往前每一次更新质因数的id, 若没有,默认加0,nlogn复杂度: 我用暴力竟然水过去了:) */ #include <cst ...
 - Mr. Kitayuta's Colorful Graph CodeForces - 506D(均摊复杂度)
		
Mr. Kitayuta has just bought an undirected graph with n vertices and m edges. The vertices of the gr ...
 - Codeforces 830C On the Bench
		
题意:给你n个数,问有多少种排列方式使得任意两个相邻的数的乘积都不是完全平方数 我好弱,被组合和数论吊着打... 首先我们可以把每个数中固有的完全平方数给分离出来,那么答案其实就只与处理后的序列相关. ...
 - Codeforces 830C Bamboo Partition 其他
		
原文链接https://www.cnblogs.com/zhouzhendong/p/CF830C.html 题解 把问题转化成求最大的 $d$ ,满足$$\sum_{1\leq i \leq n}( ...
 - Codeforces 830C Bamboo Partition (看题解)
		
Bamboo Partition 列公式, 整除分块, 想不到, 好菜啊. #include<bits/stdc++.h> #define LL long long #define fi ...
 - words2
		
餐具:coffee pot 咖啡壶coffee cup 咖啡杯paper towel 纸巾napkin 餐巾table cloth 桌布tea -pot 茶壶tea set 茶具tea tray 茶盘 ...
 - 嵌入式开发—C语言面试题
		
嵌入式开发—C语言面试题 源地址:http://blog.csdn.net/xdx2ct1314/article/details/7358929 1. 用预处理指令#define 声明一个常数,用 ...
 - 匹夫细说C#:委托的简化语法,聊聊匿名方法和闭包
		
0x00 前言 通过上一篇博客<匹夫细说C#:庖丁解牛聊委托,那些编译器藏的和U3D给的>的内容,我们实现了使用委托来构建我们自己的消息系统的过程.但是在日常的开发中,仍然有很多开发者因为 ...
 - bzoj 2058+2059+2060 Usaco2010 Nov
		
三道金组比较容易的题目.. 2058 首先交换次数就是逆序对数,因为只能交换相邻的两数 先对原序列找逆序对数 用树状数组nlogn求出 然后O(n)依次求出其循环序列的逆序对数 比如 3 5 4 2 ...
 
随机推荐
- (原、整)Unreal源码 CoreUbject- Uobject
			
(原.整) Unreal源码 CoreUbject- Uobject 类别 [随笔分类]Unreal源码搬山 @author:白袍小道 随缘那啥 这里还是属于UE ...
 - HDU 4109 Instrction Arrangement(DAG上的最长路)
			
把点编号改成1-N,加一点0,从0点到之前任意入度为0的点之间连一条边权为0的边,求0点到所有点的最长路. SPFA模板留底用 #include <cstdio> #include < ...
 - C++ 11 智能指针 lamda  以及一个   围棋程序
			
lamda表达式使用 char* p = "Hello world"; ,nl = ; for_each(p,p+, [&](char i){ if(i=='e') ne+ ...
 - Linux 内核数据结构bitmap
			
#include <stdio.h> #include <stdlib.h> #define MAX_PRIO 10000 #define BITS_PER_LONG 32 # ...
 - poj  2299 归并排序求逆序数  (可做模板)
			
Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 48077 Accepted: 17533 Description In ...
 - 再看数据库——(5)Group By与Order By
			
在使用sql语句时,很多人都会分不清order by与group by,其实简单的说: order by -- 排序 group by --分组 1.order by是行的排序,默认为升序. 有两种方 ...
 - c# 对XML 解析 和 序列化
			
/// <summary> /// 解析XML 数据 /// </summary> /// <param name="re"></para ...
 - java 图形化界面笔记(1)
			
目录 JFrame窗体......................................................................................... ...
 - 个人收藏的移动端网页布局rem解决方案
			
写移动端项目时,总是会纠结是用css3 media query 还是用rem.移动端框架挺多,但是因为项目都比较小,不考虑使用. 无意在网上找到一个移动端rem布局的解决方案,经个人实践,目前未出现什 ...
 - BZOJ5299 [Cqoi2018]解锁屏幕  【状压dp】
			
题目链接 BZOJ5299 题解 就一个毒瘤卡常题..写了那么久 设\(f[i][s]\)表示选了集合\(s\)中的点,最后一个是\(i\),进行转移 要先预处理出两点间的点,然后卡卡常就可以过了 # ...