HDU 4937 Lucky Number 搜索
题意:
给你一个数,求在多少种不同的进制下这个数每一位都是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 搜索的更多相关文章
- 枚举 + 进制转换 --- hdu 4937 Lucky Number
Lucky Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)To ...
- 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 求出 ...
- HDU 4937 Lucky Number (数学,进制转换)
题目 参考自博客:http://blog.csdn.net/a601025382s/article/details/38517783 //string &replace(iterator fi ...
- 2014多校第七场1003 || HDU 4937 Lucky Number
题目链接 题意 : 给定一个十进制n,让你转化成某个进制的数,让这个数只包含3 4 5 6这些数字,这个进制就成为n的幸运数字,输出有多少幸运数字,例如19,5进制表示是34,所以5是19的一个幸运数 ...
- hdu 4937 Lucky Number
虽然算法清晰的不能再清晰,但是实现总是边角料错这错那. 题目大意: 给出n,找出一些进制,使得n在该进制下仅为3,4,5,6表示 解题思路: 首先,4-10000进制直接枚举计算出每一位 此外,最多只 ...
- HDU 4937 Lucky Number 规律题_(:зゝ∠)_
把全部合法的进制打出来会发现合法的进制都是在 n/3 n/4 n/5的边上 然后暴力边上的进制数.. #include <cstdio> #include <set> type ...
- HDOJ 4937 Lucky Number
当进制转换后所剩下的为数较少时(2位.3位),相应的base都比較大.能够用数学的方法计算出来. 预处理掉转换后位数为3位后,base就小于n的3次方了,能够暴力计算. . .. Lucky Numb ...
- HDU 3346 Lucky Number
水题 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> us ...
- CF1478-B. Nezzar and Lucky Number
CF1478-B. Nezzar and Lucky Number 题意: 题目给出一个数字\(d(1\leq d \leq 9)\)代表某个人最喜欢的数字. 题目定义了幸运数字,它的含义为:若一个数 ...
随机推荐
- POJ 3723 Conscription (Kruskal并查集求最小生成树)
Conscription Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14661 Accepted: 5102 Des ...
- .NET深入解析LINQ框架1
1.LINQ简述 2.LINQ优雅前奏的音符 2.1.隐式类型 (由编辑器自动根据表达式推断出对象的最终类型) 2.2.对象初始化器 (简化了对象的创建及初始化的过程) 2.3.Lambda表达式 ( ...
- SpringBoot学习笔记(10)-----SpringBoot中使用Redis/Mongodb和缓存Ehcache缓存和redis缓存
1. 使用Redis 在使用redis之前,首先要保证安装或有redis的服务器,接下就是引入redis依赖. pom.xml文件如下 <dependency> <groupId&g ...
- 优动漫PAINT简简单单绘画绣球花
本文分享使用优动漫PAINT简简单单绘画绣球花教程: 相关资讯还可以关注http://www.dongmansoft.com 最后告诉你绣球花的花语,还是很和谐美好的呢! 绣球花没有茉莉花的芳香四溢, ...
- Dapper丶DapperExtention,以及AbpDapper之间的关系,
在一些开发上,由于系统的迭代上面,不能立即使用ABP框架一些框架,框架是死的,框架是死的,框架中的一些东西很值得我们学习.例如DDD架构设计,Dto数据传输对象,以及AutoMapper.仓储,依赖注 ...
- 总结Ajax的一些细节
Ajax的总结 主要从Ajax是什么?可以用来干什么?基本要素,优缺点,执行过程,跨域的解决方案等几方面来解释. Ajax是什么? Ajax主要用来实现客户端与服务器端的异步通信效果,实现页面的局部刷 ...
- luogu P4139 上帝与集合的正确用法(扩展欧拉定理)
本蒟蒻现在才知带扩展欧拉定理. 对于任意的\(b\geq\varphi(p)\)有 \(a^b\equiv a^{b\ mod\ \varphi(p)+\varphi(p)}(mod\ p)\) 当\ ...
- BZOJ 2246 [SDOI2011]迷宫探险 (记忆化搜索)
题目大意:太长了,略 bzoj luogu 并没有想到三进制状压 题解: 3进制状压陷阱的状态,0表示这种陷阱的状态未知,1已知危险,2已知不危险 然后预处理出在当前状态下,每种陷阱有害的概率,设为$ ...
- 是否可以从一个static方法内部发出对非static方法的调用
不可以.因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方 法调用,而static方法调用时不需要创建对象,可以直接调用.也就是说,当一个static方法被调用时 ...
- #undef 的用法
在Visual Studio2008中编写如下代码: #include <iostream> using namespace std; int main() { #define MODI ...