题意:
我们将3,4,5,6认为是幸运数字。给定一个十进制数n。现在可以讲起任意转换成其他进制,但转换后的数必须是由3,4,5,6构成的,而这个进制称为幸运进制。问有多少个幸运进制。若有无数个,则输出-1。例如19在5进制下是34,所以5是幸运进制。
题解:
先考虑特殊情况,所情况下会有无穷个?只有n=3,4,5,6的时候,因为这几个数在大于n的进制下都是他本身。。注意特殊情况不包括33,343这些(我一开始就死在这里了,wa了三次)。因为33在34进制下就不是33了(类似于10在16进制下就是A了)。
我们知道n=a0+a1*x+a2*x^2+...,其中x为进制。由于n达到1e12,所以我们分情况讨论。
1)a0形式,我们已经在特殊情况中指出,只有无穷个的时候才会符合条件
2)a0+a1*x形式,枚举a0,a1,我们判断(n-a0)是否能被a1整除,以及x是否大于max(a0,a1)即可。
3)a0+a1*x+a2*x^2,我们枚举a0,a1,a2,那么就相当于解一元二次方程。判断是否有整数解,是否整数解x>max(a0,a1,a2)即可。
4)不在上述三种形式内的,那么进制x最大也不会x^3>n,不然就会变成上述三种的形式。我们就可以枚举进制然后判断是否为幸运进制了。由于x^3<=n,所以复杂度只有1e4。
注意:就是上述的特殊情况,死的惨惨的。。
代码:
#include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #include <vector> #include <map> #include <iostream> #include <algorithm> using namespace std; #define LL __int64 const int maxn=1e5+10; int main() { //freopen("D:\\in.txt","r",stdin); int T; scanf("%d",&T); int tt=0; while(T--) { LL n,t,ans=0; LL i,j,k; LL a,b,c,d,x; scanf("%I64d",&n); if(n>=3&&n<=6){printf("Case #%d: -1\n",++tt);continue;} //a1+a2*x,x>max(a1,a2) for(i=3;i<=6;i++) { for(j=3;j<=6;j++) { if((n-i)%j==0&&(n-i)/j>max(i,j)) { //printf(" %I64d+%I64d*%I64d\n",i,j,(n-i)/j); ans++; } } } for(i=3;i<=6;i++) { for(j=3;j<=6;j++) { for(k=3;k<=6;k++) { a=i;b=j;c=k-n; d=(LL)sqrt(b*b-a*c*4+0.5); if(d*d!=b*b-a*c*4)continue; if((d-b)%(a*2))continue; x=(d-b)/(a*2); if(x>max(max(i,j),k)) { //printf(" %I64d+%I64d*%I64d+%I64d*%I64d^2\n",k,j,x,i,x); ans++; } } } } for(i=2;i*i*i<=n;i++) { t=n; while(t) { if(t%i<3||t%i>6)break; t=t/i; } if(!t) { ans++; } } printf("Case #%d: %I64d\n",++tt,ans); } return 0; }