COGS 2482. Franky的胡子【二分,高精度】

2482. Franky的胡子

☆   输入文件:beard.in   输出文件:beard.out   简单对比
时间限制:1 s  
内存限制:128 MB

【题目描述】

Franky很苦恼他一直不长胡子。

看到同学大叔一样的胡子,Franky总是很无耻的偷笑...

有一天,杨老师要带Franky参加n天的外出培训!!!好开心!!

在火车上,Franky突然发现自己长了胡子!

杨老师带Franky去查了基因图谱==(好贴心)

并且发现:

1.胡子初始每天深夜都会长v cm;

2.每次在剃掉胡子之后胡子增长的速度会增加s cm/天;

Franky很伤心,并且由于来时并不需要剃须刀,所以只能借杨老师的,但是杨老师很吝啬(哼( ﹁ ﹁ ) ~→)

他只允许Franky使用x次剃须刀,而且只允许在晚上睡前用。

【输入格式】

输入格式:

一行,n,s,v,x四个整数。

【输出格式】

输出在培训期间Franky的胡子最长的那天胡子的长度最短值。

【样例输入】

6 1 1 2

【样例输出】

4

【提示】

保证对于20%的数据,x,n,c,s<=10;

对于70%的数据,x,n<=5000,c,s<=100;

对于100%的数据,x,n<=100000,c,s<=10000;

【来源】

题目链接:http://cogs.cf/cogs/problem/problem.php?pid=2482

经典的二分答案例题

注意到题目要求最大值最小,最大最小是一个典型的二分答案型题目。

所以我们可以二分一个最长的胡子长度,初始我们使R=一个极大值,l=1,mid = (r + l) / 2,然后用模拟的方式运行检验,在运行的过程中如果出现当前胡子长度大于我们二分出的mid我们就需要把当前的胡子剪掉,如果我们n天走下来剪胡子的次数 < x那么对于这个mid值是可行的那么我们让r=mid尝试能不能继续缩小答案,如果>mid那么证明不行我们要扩大答案继续检验,我们不必关心对于一个可行的mid中最长的那个小于mid的情况,因为在二分的过程中我们一定会二分出这个情况。时间复杂度O(nlogm)。

下面给出AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 ll n,s,v,x;
 5 bool check(ll len)
 6 {
 7     ll speed=v,length=0,ci=x;
 8     for(ll i=1;i<=n;i++)
 9     {
10         length+=speed;
11         if(length>len)
12         {
13             length=0;
14             speed+=s;
15             ci--;
16             i--;
17         }
18         if(ci==-1)
19             return 0;
20     }
21     return 1;
22 }
23 int main()
24 {
25     freopen("beard.in","r",stdin);
26     freopen("beard.out","w",stdout);
27     cin>>n>>s>>v>>x;
28     ll l=0;
29     ll r=n*(s+v);
30     while(l<=r)
31     {
32         ll mid=(l+r)/2;
33         if(check(mid))
34             r=mid-1;
35         else l=mid+1;
36     }
37     cout<<l<<endl;
38     return 0;
39 }
时间: 2024-10-03 23:28:53

COGS 2482. Franky的胡子【二分,高精度】的相关文章

高精度开跟模板

实质:二分+高精度乘法 1 struct node { 2 typedef ll INT; 3 static const INT S=100000000; 4 static const int S_n=9; 5 static const int SIZE=305; 6 INT a[SIZE]; int len, tag; 7 node() { len=1; CC(a, 0); } 8 node(char *s) { len=1; CC(a, 0); *this=s; } 9 node(INT x

POJ 2109 巧妙解法

Int最大是10^9.所以一般思路是二分+高精度.但是double 范围是10^(-307)-10^308所以可以用double型.k^n=p.所以有k=p^(1/n). 见代码: #include<stdio.h>#include<string.h>#include<iostream>using namespace std;#include<math.h> int main(){     double n, p;     while(cin >>

hdu2199 (高精度二分)

二分的高精度模板 二分法的精度使用方法 #include<cstdio> #define F(x) 8*x*x*x*x+7*x*x*x+2*x*x+3*x+6 int main() { int t; scanf("%d",&t); while(t--){ double y,l=0,r=100,mid; scanf("%lf",&y); if(y<6||y>807020306){ puts("No solution!&

【二分】【高精度】Vijos P1472 教主的集合序列

题目链接: https://vijos.org/p/1472 题目大意: S1={1,2,3…n}.当i>1时,Si为集合Si-1中任意两个不相同数之和的集合. 将每个集合中所有元素取出,集合Si的数放在集合Si+1的数的前面,同一个集合数从小到大排序,这样得到一个序列L. 题目输入n和K,求L中第K个数是多少. 变态的数据范围:K≤101000,1<n≤1000:且数据保证当n≤3时,K≤900000. 题目思路: [二分][高精度] 真是恶心的一道题啊..打了好久. S1={1,2,...

【COGS】147. [USACO Jan08] 架设电话线(二分+spfa)

http://cojs.tk/cogs/problem/problem.php?pid=147 学到新姿势了orz 这题求的是一条1-n的路径的最大路径最小. 当然是在k以外的. 我们可以转换一下. 求比某个价值大的某条路径的数量,只要小于k,那么这一定是一个可行解.因为其它的边都是小于了这个价值.(当然这里指的都是需要价格的) 我们在求这条路径时还要满足这条路径比这个价值大的边要最小,当然用最短路求. 那么问题就转换为,给定一个价值,求1-n的一条路径满足比这个价值大的边最少,而且少于k. 那

POJ2109 高精度(含大数开方)+二分

1 高精度(含大数开方)+二分 一个技巧和三点注意: 技巧:假设k^n=p;(k的n次方),那么p的位数/n得到的是k的位数!例如:n=7,p=4357186184021382204544,p的位数为22,用22/7的结果向上取整,得到4,即为k的位数,也就是说k的取值范围是1000~9999.(引自code_pang)不利用这一点,高精度+直接二分,也会超时.用这一个技巧合理缩小二分的范围. 注意:看code的main中的注释. (二分思想不熟练,因为二分算法很高效,所以一定要暴力点直接确定l

POJ - 2109 Power of Cryptography(高精度log+二分)

Current work in cryptography involves (among other things) large prime numbers and computing powers of numbers among these primes. Work in this area has resulted in the practical use of results from number theory and other branches of mathematics onc

cogs 2652. 秘术「天文密葬法」(0/1分数规划 长链剖分 二分答案 dp

http://cogs.pro:8080/cogs/problem/problem.php?pid=vSXNiVegV 题意:给个树,第i个点有两个权值ai和bi,现在求一条长度为m的路径,使得Σai/Σbi最小. 思路:二分答案得p,把每个点权值变成ai-p*bi,看是否存在长为一条长为m的路使总和<=0. tag数组表示从当前位置沿最长链走到底的值,dp数组初值表示从当前位置的重儿子走到底的值(加负号),用tag[...]+dp[..]维护从当前节点往下走若干步得到的最小值(只更新dp数组

BZOJ 1213 HNOI2004 高精度开根 二分+高(Py)精(thon)度

题目大意:求n^(1/m) 一大早水个Python- - 直接开根尼玛过不去- - 需要二分- - m,n=int(raw_input()),int(raw_input()) l,r=0,1 while r**m<=n: l=r;r=r*2 while l+1<r: mid=(l+r)//2 if mid**m<=n: l=mid else: r=mid if r**m<=n: print r else: print l