题意:

  给你一个数,求在多少种不同的进制下这个数每一位都是3、4、5、6中的一个。

思路:  

  搜索。枚举这个数在任意进制下的表示,判断是否合法。当数字只有3、4、5、6时,必定有无穷种。

  因为数字太大,所以直接枚举必定会超时。

  下面有两种剪枝的方法:

    1. 先枚举最后一位的情况。 假设数字n在base进制下表示为 a[n]...a[0],即 n = a[0] + a[1]*base^1 + ... + a[n]*base^n。

   则 n - a[0] = a[1]*base^1 + ... + a[n]*base^n = base * (a[1] + ... + a[n]*base^(n-1) )。 即n - a[0] 是base 的倍数。

   所以,我们可以确定base是n-a[0]的因子。 所以,我们可以先枚举在某个进制下的末位a[0],然后在枚举 n-a[i]的因子就好了。

  代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <time.h> using namespace std; typedef __int64 ll; const int INF = <<;
const int MAXN = (int) 1e6+; int Prime[MAXN], len;
bool is[MAXN]; ll f[];
int cnt[], num; void factor(ll x) { //分解质因数
num = ;
if (x==) return ;
for (int i = ; i < len; i++) if ((x%Prime[i])==) {
f[num] = Prime[i];
cnt[num] = ;
while (x%Prime[i]==) {
x /= Prime[i];
cnt[num]++;
}
num++;
if (x==) break;
if (x<Prime[len-] && !is[x]) break;
}
if (x!=) {
f[num] = x;
cnt[num++] = ;
}
} ll n;
int ans; void dfs(ll base, int deep) { //枚举可以重复的组合
if (deep==num) {
if (base < ) return ;
ll tmp = n, t;
while (tmp) {
t = tmp%base;
if (!(<t&&t<)) return ;
tmp /= base;
}
ans++;
return ;
}
ll tmp = base;
for (int i = ; i <= cnt[deep]; i++) {
dfs(tmp, deep+);
tmp *= f[deep];
}
} void solve() {
scanf("%I64d", &n);
ans = ;
if (<n&&n<) {
puts("-1");
return ;
}
for (int i = ; i < ; i++) if (n-i>) { //枚举末位
factor(n-i);
dfs(1LL, );
}
printf("%d\n", ans);
} int main() {
#ifdef Phantom01
freopen("HDU4937.in", "r", stdin);
#endif //Phantom01 memset(is, false, sizeof(is));
len = ;
for (int i = ; i < MAXN; i++) if (!is[i]) {
Prime[len++] = i;
for (ll j = i*; j < MAXN; j+=i)
is[j] = true;
} int T;
scanf("%d", &T);
for (int i = ; i <= T; i++) {
printf("Case #%d: ", i);
solve();
} return ;
}

    2. 当n在base进制下为一位数的时候,为3、4、5、6,则一定存在无穷种进制下都是这个一位数。

     两位数时, n = a[1]*base + a[0]

     三位数时,n = a[2]*base^2 + a[1]*base + a[0]

    因此,在n是两位数或者三位数时,我们可以枚举这个两位数或者三位数,求得有多少个base能得到这个两位数或三位数。

    当 n 是4位数或者更多时, n = a[0] + a[1]*base^1 + ... + a[n]*base^n > 3*base^4 。即 3*base^4 < n <= 1e12。 所以,此时base < 7000。

    所以,我们可以暴力枚举n是四位数的情况,而这时的base不会大于7000 。所以就不会超时了。

  代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <time.h> using namespace std; typedef __int64 ll;
const int INF = <<; ll n;
int ans; inline int function1(ll a, ll b) { //n = a*base + b
if (((n-b)%a)!=) return ; //如果不是整数
ll tmp = (n-b)/a;
if (a>=tmp || b>=tmp) return ; //如果位数大于进制数
return ;
} inline int function2(ll a, ll b, ll c) { //n = a*base^2 + b*base + c
c -= n;
ll t1 = b*b-*a*c;
if (t1<) return ;
ll t2 = (ll) sqrt((double)t1);
if (t2*t2!=t1) return ;
if (((t2-b)%(*a))!=) return ;
t1 = (t2-b)//a;
if (t1<=a || t1<=b || t1<=c || t1<=) return ;
return ;
} inline bool check(int base) {
ll t = n, cnt = , tt;
while (t>) {
tt = t%base;
if (!(<tt&&tt<)) return false;
t /= base;
cnt++;
}
return cnt>;
} void solve() {
scanf("%I64d", &n); if (<n&&n<) {
puts("-1");
return ;
} ans = ;
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
for (int k = ; k < ; k++) {
ans += function2(i, j, k);
}
ans += function1(i, j);
}
}
ll len = min(n, 7000ll);
for (int i = ; i < len; i++)
ans += check(i) ? : ; printf("%d\n", ans);
} void ttt(int i) {
int t = ;
printf("%d:", i);
while (t) {
printf("%d ", t%i);
t /= i;
}
puts("");
} int main() {
#ifdef Phantom01
freopen("HDU4937.in", "r", stdin);
// freopen("HDU4937.txt", "w", stdout);
#endif //Phantom01 int T;
scanf("%d", &T);
for (int i = ; i <= T; i++) {
printf("Case #%d: ", i);
solve();
} return ;
}

HDU 4937 Lucky Number 搜索的更多相关文章

  1. 枚举 + 进制转换 --- hdu 4937 Lucky Number

    Lucky Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)To ...

  2. HDU 4937 Lucky Number(2014 Multi-University Training Contest 7)

    思路:先枚举  a*bas +b = n  求出 bas 在sqrt(n)到n的  (bas>a&&bas>b) 再枚举  a*bas*bas+b*bas+c =n  求出 ...

  3. HDU 4937 Lucky Number (数学,进制转换)

    题目 参考自博客:http://blog.csdn.net/a601025382s/article/details/38517783 //string &replace(iterator fi ...

  4. 2014多校第七场1003 || HDU 4937 Lucky Number

    题目链接 题意 : 给定一个十进制n,让你转化成某个进制的数,让这个数只包含3 4 5 6这些数字,这个进制就成为n的幸运数字,输出有多少幸运数字,例如19,5进制表示是34,所以5是19的一个幸运数 ...

  5. hdu 4937 Lucky Number

    虽然算法清晰的不能再清晰,但是实现总是边角料错这错那. 题目大意: 给出n,找出一些进制,使得n在该进制下仅为3,4,5,6表示 解题思路: 首先,4-10000进制直接枚举计算出每一位 此外,最多只 ...

  6. HDU 4937 Lucky Number 规律题_(:зゝ∠)_

    把全部合法的进制打出来会发现合法的进制都是在 n/3 n/4 n/5的边上 然后暴力边上的进制数.. #include <cstdio> #include <set> type ...

  7. HDOJ 4937 Lucky Number

    当进制转换后所剩下的为数较少时(2位.3位),相应的base都比較大.能够用数学的方法计算出来. 预处理掉转换后位数为3位后,base就小于n的3次方了,能够暴力计算. . .. Lucky Numb ...

  8. HDU 3346 Lucky Number

    水题 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> us ...

  9. CF1478-B. Nezzar and Lucky Number

    CF1478-B. Nezzar and Lucky Number 题意: 题目给出一个数字\(d(1\leq d \leq 9)\)代表某个人最喜欢的数字. 题目定义了幸运数字,它的含义为:若一个数 ...

随机推荐

  1. 还是bib问题

    虽然昨天把添加bib的基本问题解决了,但是bib的参考文献没有了中括号.查了一下华东师大,只是给出了如何去掉中括号的方法. http://math.ecnu.edu.cn/~latex/doc.htm ...

  2. SQLServer 错误: 15404,维护计划无法执行

    错误症状: D:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\LOG下面的ERROELOG,用文本打,查看运行维维计划不成功是生成的错误日志详细信 ...

  3. hiho151周*

    题目链接 题目大意:依次在给定的三维坐标上垒方块,对于一个新的坐标需满足两个条件 1:六个方向有相邻的方块或者z==1[题目说明了初始状态是:所有z==0的位置都有方块] 2:该位置存在一条到无穷远处 ...

  4. iOS系统的特点-iOS为什么运行更流畅

    1.进程管理机制-不允许后台进程: 2.用户事件响应优先级: 3.GPU加速: 4.系统内存管理机制: 5.运行机制-机器码直接运行-非虚拟机.

  5. 给DOM操作生成的元素添加事件

    问题:通过js给页面添加新元素,并给该元素添加绑定事件,但新添加的元素上却没有绑定任何事件. 常见例子:在处理表格的时候,每行行末有个删除按钮,如下图.点击删除按钮的时候删除这一行. //html部分 ...

  6. POJ3764 The xor-longest Path(字典树)

    题意 给你一棵树,n个节点,n-1条边每条边i都有一个权值wi.定义任意两点间的权值为:这两点间的路径上的所有边的值的异或.比如a点和b点间有i,j,k三条边,那么ab两点间的权值为:wi^wj^wk ...

  7. javaweb集成swagger

    一.添加依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-sw ...

  8. OpenJDK源码研究笔记(一)-参数检查&抛出带关键错误提示信息的异常

    OpenJDK源码研究笔记系列文章,是我在阅读OpenJDK7源码的过程中的一些体会.收获.看法. 把研究过程中的成长和收获一点点地整理出来,是对自己研究学习的一个小结,也有可能给学习Java的一些同 ...

  9. Mysql学习总结(29)——MySQL中CHAR和VARCHAR

    MySQL数据库的字符(串)类不要以为字符类型就是CHAR,CHAR和VARCHAR的区别在于CHAR是固定长度,只要你定义一个字段是CHAR(10),那么不论你存储的数据是否达到了10个字节,它都要 ...

  10. vps上运行serv-u的问题

    为了给产品环境建个测试站,今天特意申请一个vps来做开发用,但运行了Serv-U的ServUDaemon.exe后始终提示: 响应: 530 User czhan cannot log in. 很无语 ...