题意:我们将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; }