B - 缺失的数据范围

21 篇文章 0 订阅
2 篇文章 0 订阅

点击打开链接

著名出题人小Q出过非常多的题目,在这个漫长的过程中他发现,确定题目的数据范围是非常痛苦的一件事。

每当思考完一道题目的时间效率,小Q就需要结合时限以及评测机配置来设置合理的数据范围。

因为确定数据范围是一件痛苦的事,小Q出了非常多的题目之后,都没有它们设置数据范围。对于一道题目,小Q会告诉你他的算法的时间复杂度为O(nalogbn),且蕴含在这个大O记号下的常数为1。同时,小Q还会告诉你评测机在规定时限内可以执行k条指令。小Q认为只要na(log2n)b不超过k,那么就是合理的数据范围。其中,x表示最小的不小于x的正整数,即x上取整。

自然,小Q希望题目的数据范围n

越大越好,他希望你写一个程序帮助他设置最大的数据范围。
Input 第一行包含一个正整数 T(1T1000),表示测试数据的组数。

每组数据包含一行三个正整数 a,b,k(1a,b10,106k1018),分别描述时间复杂度以及允许的指令数。 Output 对于每组数据,输出一行一个正整数 n,即最大可能的 n。 Sample Input
3
1 1 100000000
2 1 100000000
1 3 200000000
Sample Output
4347826
2886
48828

思路:二分

那么我么应该设置左区间为0,右区

间为题目中k的最大范围10的18次。因为输入的数据特别的巨大,所以我们要用unsigned long long来定义变量

否则会装不下。我们用一个mid来保存二分出来的结果,如果吗mid>k那么右区间则太大了,右区间便变成了m-1。为什么右区间不是mid呢,因为mid已经被我们判断过了大于k,所以mid-1,同理可得,当mid<k,左区间便成了mid+1。

那么二分的退出条件也可以得出,那便是l>r时。最后输出r便是答案了。但有一个问题我们仍需要解决,就是公式中的次幂相乘的话值太大了 ,它会爆 unsigned long long 所以我们可以把k整除等式左边的值,如果在过程中左边还没除外,k已经变零了,那么mid一定是大于了k,反之mid小于k了。

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
vector <int>ve[100005];
unsigned long long a,b,k;
int con(ll mid)
{
    int i,j;
    unsigned long long kk=k;
 //mid^a与k比较大小
    for(i=0;i<a;i++)
    {
       if(kk/mid<=0)
         return 0;
       else
         kk/=mid;
    }
    unsigned ans=(unsigned long long)ceil(log2(mid));  //ceil()为向上取整函数
    if(ans==0)//(有可能log2(sum)==0)这个时候直接返回太小了 防止除零  
      return 1;
   //m^b与kk比较大小
    for(i=0;i<b;i++)
    {
       if(kk/ans<=0)
         return 0;
       kk/=ans;
    }
    return 1;
}
int main()
{
   int t,i,j;
   scanf("%d",&t);
   while(t--)
   {
      scanf("%llu%llu%llu",&a,&b,&k);//%llu为无符号的long long
      unsigned long long l=0,r=1e18;
      while(1)
      {
         if(l>r)
           break;
         if(con((l+r)/2))
           l=(l+r)/2+1;
         else
           r=(l+r)/2-1;
      }
      printf("%llu\n",r);
   }
   return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2020/3/16

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值