题意:我们将3,4,5,6认为是幸运数字。给定一个十进制数n。现在可以讲起任意转换成其他进制,但转换后的数必须是由3,4,5,6构成的,而这个进制称为幸运进制。问有多少个幸运进制。若有无数个,则输出-1。例如19在5进制下是34,所以5是幸运进制。
//我们将n这个数在x进制下的表示记为:n=a0+a1*x+a2*x^2+a3*x^3+.....
我们发现当n表示为x进制下的四位数时,就有 a3*x^3+.....而n最大只有1e12,因此x最大就只需要取到 10000 即可表示所有1e12内的数,
首先如果n表示为X进制, 当n是一位数时,显然只有 n= 3 4 5 6符合要求,当然此后所有进制下,n都合法,因此答案-1。
当n表示为2位数, //case1 n=a0+a1*x;,我们只需要枚举a0,a1就可以得到x的个数
当n表示为三位数 //case2 n=a0+a1*x+a2*x^2,我们需要解这个一元二次方程,判断解x是否为正整数,
当n表示为4位数以及以上时 显然X进制小最小的四位数也是 x^3啦,因此 只要n>=x^3,我们就可以确保 n至少会被表示为大于等于四位数。
因此只要枚举符合x^3<=n的所有x即可,显然x不超过1w个 因此复杂度没问题
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
__int64 max(__int64 a,__int64 b)
{return a>b?a:b;}
const double pi=acos(-1.0);
double eps=0.00000001;
int main()
{
int t;cin>>t;
int cnt=1;
while(t--)
{
__int64 n;
scanf("%I64d",&n);
//case0
if (n==3||n==4||n==5||n==6)
{
printf("Case #%d: -1\n",cnt++); continue;
}
__int64 i,j,k;
__int64 ans=0;
//我们将n这个数在x进制下的表示记为:n=a0+a1*x+a2*x^2+a3*x^3+.....
//case1 n=a0+a1*x;
for (i=3;i<=6;i++)
for (j=3;j<=6;j++)
if ((n-i)%j==0)
if ((n-i)/j>max(i,j))ans++;
//case2 n=a0+a1*x+a2*x^2
//a2 * x^2 + a1* x +a0-n=
//del=sqrt(a1*a1-4*a2*(a0-n))0
//x1= (-a1+del) /2/a2;
//x2= (-a1-del)/2/a2;
for (i=3;i<=6;i++)
{
for (j=3;j<=6;j++)
{
for (k=3;k<=6;k++)
{
if (j*j-4*k*(i-n)<0) continue;
__int64 del=(__int64)sqrt(j*j-4*i*(k-n)+0.5);
if (del*del!=j*j-4*i*(k-n))continue; //判断是否整数
if ((-j+del)%(2*i))continue;
__int64 x=(-j+del)/(2*i);
if(x>max(max(i,j),k)) ans++; //进制数必须大于各位数
if ((-j-del)%(2*i))continue;
__int64 x2=(-j-del)/(2*i);
if (x==x2) continue;
if(x2>max(max(i,j),k)) ans++;
}
}
}
for(i=1;i*i*i<=n;i++)//i进制下最小的四位数是 i^3,如果n>=i^3,则n一定是会被表示为i进制下的至少四位数的数,由于n_max=1e12,因此i最多枚举到1w就OK
{
__int64 tmp=n;
int fail=0;
while(tmp)
{
__int64 test=tmp%i;
tmp/=i;
if (test>=3&&test<=6)
continue;
else
{fail=1;break;}
}
if (!fail)
ans++;
}
printf("Case #%d: %I64d\n",cnt++,ans);
}
return 0;
}