zoukankan      html  css  js  c++  java
  • [二分]煤气灶

    链接:https://ac.nowcoder.com/acm/problem/21860
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 32768K,其他语言65536K
    64bit IO Format: %lld

    题目描述

    小j开始打工,准备赚钱买煤气灶。
    第一天,小j的工资为n元,之后每天他的工资都比前一天多d元。
    已知煤气灶需要m元,求小j最少工作几天才能买到煤气灶。

    输入描述:

    四个整数 n,m,d,x
    分别表示小j第一天的工资,煤气灶的价格,工资每天的增长量,答案不超过x

    输出描述:

    一个数表示答案
    示例1

    输入

    复制
    10 100 20 100

    输出

    复制
    4

    说明

    10+30+50+70>=100

    备注:

    0≤n,d≤1e9,n+d>0
    1≤m≤1e18
    1≤x≤1e9

    题意:每天都能得到工资,一开始为n,每一天都可能在比前一天多领d(注意d可能为0),问最少多少天你领的工资的总和能超过买煤气灶需要的m元,天数不超过x
    思路:求和问题,每天都可能多增加d的值,所以这是一个初值为n,公差为d的等差数列求和,等差数列求和公式:Sn=a0*n+(n*(n-1)*d/2),又注意到m最大是1e18,若要让等差数列之和Sn>=m,则Sn会超出long long的范围,所以要对公式进行变形,
    设n为初值,in为天数,d为公差,m为总和至少需要大于的值,得到

        n*in+(in*(in-1)*d)/2>=m
        2*(n*in)+(in(in-1)*d)>=2*m
        in*(in-1)*d>=2*(m-(n*in))

    同时注意到1<=in<=x,所以就想到二分一下答案

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 ll n,m,d,x;
     5 bool check(ll in){
     6     return in*(in-1)*d>=2*(m-(n*in));
     7 }
     8 int main(){
     9     cin>>n>>m>>d>>x;
    10     ll l=1,r=x,mid=(l+r)>>1;
    11     while(l<r){
    12         if(check(mid))r=mid;
    13         else l=mid+1;
    14         mid=(l+r)>>1;
    15     }
    16     printf("%lld
    ",mid);
    17 }
    18 /***
    19 n*in+(in*(in-1)*d)/2>=m
    20 2*(n*in)+(in(in-1)*d)>=2*m
    21 in*(in-1)*d>=2*(m-(n*in))
    22 ***/
     
  • 相关阅读:
    LeetCode 654. 最大二叉树
    LeetCode 617. 合并二叉树
    LeetCode 234. 回文链表
    LeetCode 328. 奇偶链表
    LeetCode 24. 两两交换链表中的节点
    LeetCode 21. 合并两个有序链表
    LeetCode 876. 链表的中间结点
    顺序表的定义及其相关基本操作
    LeetCode 206. 反转链表
    LeetCode 111. 二叉树的最小深度
  • 原文地址:https://www.cnblogs.com/Railgun000/p/11293710.html
Copyright © 2011-2022 走看看