HDU 4937 Lucky Number 【搜索】

来源:互联网 发布:数据集成论文 编辑:程序博客网 时间:2024/05/29 05:57

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4937

题目大意:给你T组数据,每组数据输入一个小于=1e12的数num,如果这个数的n进制下都是由3,4,5,6这四个数字组成的,则说明这个n进制是num的幸运进制,现在求一个num有几个幸运进制,如果有无限多个幸运进制则输出-1.

题解:

如果输入的num转化后是一位数,显然可以得到3,4,5,6这四个数字应该输出-1。

           如果输入的num转化后是二位数,以base作为进制的话,转换问base进制就是num=a*base+b。就是解这个二元一次方程(num已知;枚举a和b,算得base>max(a,b)即可)

           如果输入的num转化后是三位数,以base作为进制的话,转换为base进制就是num=a*base*base+b*base+c,就是枚举a,b,c算得base>max(a,b,c)即可。

   如果输入的num转化后是四位数及以上,那么其base进制可以枚举的范围是:base>min(3,4,5,6),即base最小是4。而对于其他的情况,我们只用取一个适合的大小的上界,x1+x2*base+x3*base^2+x4*base^3+...>base+x1*base+x2*base^2+x3*base^3,其上界可以取num^(1/3)即可。

   这样省了很多时间。

   

#include<iostream>#include<stdio.h>#include<cstring>#include<cmath>using namespace std;#define LL long longLL getmax(LL a,LL b){    if(a>b) return a;    else return b;}int main (){    LL T,Tt;    scanf("%d",&T);    for(LL Tt=1;Tt<=T;Tt++)    {        LL num,x1,x2,x3,ans=0;        scanf("%I64d",&num);        //如果是3,4,5,6直接输出-1        if(num>=3 && num<=6) {printf("Case #%I64d: -1\n",Tt);continue;}        //转化为base进制后是二位 x1*base + x2 = num        for(x1=3;x1<=6;x1++)         for(x2=3;x2<=6;x2++)         {             if( (num-x2)%x1==0 && (num-x2)/x1>getmax(x1,x2) )  ans++;         }        //转换为base进制后是三位        // x1*base^2 + x2*base + x3 = num        for(x1=3;x1<=6;x1++)         for(x2=3;x2<=6;x2++)          for(x3=3;x3<=6;x3++)          {              LL a=x1,b=x2,c=x3-num;              LL derta=(LL)sqrt(b*b-4*a*c+0.5);              if(derta*derta!=b*b-4*a*c) continue;              if( (derta-b)%(2*a)) continue;              if( (derta-b)/(2*a)>getmax(x1,getmax(x2,x3))) ans++;          }        //其他        for(LL i=4;i*i*i<=num;i++)  //之前把i定义成了int类型,TLE了,是int转LL的时候花了很多时间        {            LL t=num;            while(t)            {                if(t%i<3||t%i>6) break;                t=t/i;            }            if(!t) ans++;        }        printf("Case #%I64d: %I64d\n",Tt,ans);    }}

   

0 0
原创粉丝点击