Problem B. Beautiful Numbers Google APAC 2017 University Test Round E

这一题要求all of its digits become 1,所以在base B下,假设N可以表示成p位数,这个数的值就是一个等差数列,因为N是long long范围,p最多为64。

,因为B>1,给定p时,求导可以得出f(B)是单调增的。因此在给定p时,可以通过二分查找得出B的值。

这一题小数据我在二分的时候用除法比较abs(f(B))<1e-7居然WA了,不造为何。最后只能直接比较乘积,不会有精度损失。

小数据代码如下。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>

using namespace std;

//2017 RoundE Problem B. Beautiful Numbers

int T;
long long N;
int P;
long long ans;
int calnum(int base)
{
    int cnt=0;
    int num=N;
    while(num>0)
    {
        int bit=num%base;
        num=num/base;
        if(bit==1)
        {
            cnt++;
        }
        else
        {
            return -1;
        }
    }
    return cnt;
}
long long power(long long base,int p)
{
    long long ret=1;
    for(int i=0;i<p;i++)
    {
        ret*=base;
    }
    return ret;
}
long long fun(long long base,int p)
{
    //return 1.0*(1-pow(base,p))/(1-base);
    return power(base,p)-1;
}
long long binarysearch(int p)
{
    long long left=2;
    long long right=N;
    long long mid=(left+right)/2;
    int cnt=0;
    while(left<=right)
    {
        mid=(left+right)/2;
        //double tmp=fun(mid,p);
        long long tmp=fun(mid,p);
        //cout<<left<<" "<<right<<" "<<mid<<" "<<tmp<<endl;
        //if(abs(tmp-N)<1e-7)
        if(tmp==N*(mid-1))
        //if(abs(log(tmp)-log(N)-log(mid-1))<1e-7)
        {
            return mid;
        }
        if(tmp>N*(mid-1))
        //if(log(tmp)-log(N)-log(mid-1)>0)
        {
            right=mid-1;
        }
        else if(tmp<N*(mid-1))
        //else if(log(tmp)-log(N)-log(mid-1)<0)
        {
            left=mid+1;
        }
        cnt++;
//        if(cnt>10)
//        {
//            break;
//        }
    }
    return -1;

}
int main()
{
    freopen("B-large-practice.in","r",stdin);//input.txt
    freopen("output.txt","w",stdout);
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        scanf("%lld",&N);
        ans=0;
        P=log(N+1)/log(2)+1;
        //cout<<P<<endl;
        for(int p=P;p>=2;p--)
        {
            //cout<<p<<endl;
            long long tmp=binarysearch(p);
            if(tmp!=-1)
            {
                ans=tmp;
                break;
            }
        }
        printf("Case #%d: %lld\n",ca,ans);
    }
//    for(int i=2;i<=N;i++)
//    {
//        cout<<i<<" "<<calnum(i)<<endl;
//    }
    return 0;
}
大数据中,二分比较乘积是否相等会有溢出问题。在计算时,只能通过循环相加而不能直接由等比数列求和公式计算。如果之间的某 一位就已经>N了 ,就直接返回,因为算到最后第p位时值只会更大。另外,有可能在算到第i位时没有溢出且<N,但是在i+1位时溢出了(如果溢出那么一定是>N)。如果第i位的值,那么在第i+1位时一定>N。这样可以避免overflow。

eg., if  and ,那么,而累加到下一位的值是,必然>N。

因为ret是整数,下取整也没有影响。eg.,如果,那么即使和3比较,ret>3说明ret>=4,也一定满足ret>3.25。

大数据代码如下。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>

using namespace std;

//2017 RoundE Problem B. Beautiful Numbers

int T;
long long N;
int P;
long long ans;
int calnum(int base)
{
    int cnt=0;
    int num=N;
    while(num>0)
    {
        int bit=num%base;
        num=num/base;
        if(bit==1)
        {
            cnt++;
        }
        else
        {
            return -1;
        }
    }
    return cnt;
}
long long power(long long base,int p)
{
    long long ret=1;
    for(int i=0;i<p;i++)
    {
        ret*=base;
    }
    return ret;
}
int fun(long long base,int p)
{
    long long val=0;
    long long ret=1;
    for(int i=0;i<p;i++)
    {
        if(i!=0)
        {
            ret*=base;
        }
        val+=ret;
        if(val>N)//val may overflow
        {
            return 1;
        }
//        if(i<p-1)//still have one more digit to add
//        {
//            if((N-val)/base<ret)
//            {
//                return 1;
//            }
//        }
        if(i<p-1&&ret>N/base)//the above is also ok, ret is integer, then even is N/base is the floor of a decimal number, it is also fine.
        {
            return 1;
        }
    }
    if(val==N)
    {
        return 0;
    }
    else if(val<N)
    {
        return -1;
    }
}
long long binarysearch(int p)
{
    long long left=2;
    long long right=N;
    long long mid=(left+right)/2;
    int cnt=0;
    while(left<=right)
    {
        mid=(left+right)/2;
        //double tmp=fun(mid,p);
        long long tmp=fun(mid,p);
        //cout<<left<<" "<<right<<" "<<mid<<" "<<tmp<<endl;
        //if(abs(tmp-N)<1e-7)
        if(tmp==0)
        //if(abs(log(tmp)-log(N)-log(mid-1))<1e-7)
        {
            return mid;
        }
        if(tmp==1)
        //if(log(tmp)-log(N)-log(mid-1)>0)
        {
            right=mid-1;
        }
        else if(tmp==-1)
        //else if(log(tmp)-log(N)-log(mid-1)<0)
        {
            left=mid+1;
        }
        cnt++;
//        if(cnt>10)
//        {
//            break;
//        }
    }
    return -1;

}
int main()
{
    freopen("B-small-practice.in","r",stdin);
    //freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        scanf("%lld",&N);
        ans=0;
        P=log(N+1)/log(2)+1;
        //cout<<P<<endl;
        for(int p=P;p>=2;p--)
        {
            //cout<<p<<endl;
            long long tmp=binarysearch(p);
            if(tmp!=-1)
            {
                ans=tmp;
                break;
            }
        }
        printf("Case #%d: %lld\n",ca,ans);
    }
//    for(int i=2;i<=N;i++)
//    {
//        cout<<i<<" "<<calnum(i)<<endl;
//    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值