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)\)代表某个人最喜欢的数字. 题目定义了幸运数字,它的含义为:若一个数 ...
随机推荐
- [转]m3u8直播测试地址
http://www.cnblogs.com/yuandaozhe/p/5755453.html 调试m3u8的时候需要测试地址 找了几个,备用一下 安徽卫视 http://stream2.ahtv. ...
- Elasticsearch的Groovy Script自定义评分检索
需求:以索引中的boostapp列作为评分的基础分值,同时根据carpublishtime(数据的刷新时间字段)按时间进行衰减. 基于Groovy脚本实现. 1.query脚本方式: { " ...
- 「JavaSE 重新出发」02.01 基本数据类型
基本数据类型 1. 整型 注意:Java 没有任何无符号(unsigned)形式的 int.long.short 或 byte 类型. 不同进制的表示形式: 十六进制数值有一个前缀0x或0X(如0xC ...
- HCF4094(CD4094)应用
管脚说明和内部逻辑图 注:管脚图为HCF4094,内部逻辑图为CD4094(HCF4094内部逻辑图在datasheet不清晰,且复杂). 其中控制管脚有3个:STROBE-DATA-CLOCK,Ou ...
- pycharm日常填坑
pycharm坑很多,今天又遇见了,好吧 ,填坑 场景:从别的地方拷贝过来的项目,导入本地的pycharm 然后选择 然后 还会报错....心累 报错内容: django commands canno ...
- iOS面试总结(待完善)
闲的没事总结一下面试资料,先列个大纲,然后慢慢填充,一步步完善,反正也不急. 1.基本属性 2.KVC与KVO 3.代理与block 4.多线程:NSThread,GCD,NSOperation 5. ...
- luogub P4886 快递员(点分治)
记得是9月月赛题,当时做的时候觉得跟ZJOI2015幻想乡战略游戏那道题很像???,就写了,然后就写挂了... 我们发现假设当前点为根,我们算出\(m\)次询问中最远的\(a\)对点,如果这\(a\) ...
- autosar
AUTOSAR – RTE(1)基本概念 1. RTE概述 The Run-Time Environment (RTE) is at the heart of the AUTOSAR ECU arch ...
- Java数据结构-线性表之单链表LinkedList
线性表的链式存储结构,也称之为链式表,链表:链表的存储单元能够连续也能够不连续. 链表中的节点包括数据域和指针域.数据域为存储数据元素信息的域,指针域为存储直接后继位置(一般称为指针)的域. 注意一个 ...
- Python 入门学习 -----变量及基础类型(元组,列表,字典,集合)
Python的变量和数据类型 1 .python的变量是不须要事先定义数据类型的.能够动态的改变 2. Python其中一切皆对象,变量也是一个对象,有自己的属性和方法 我们能够通过 来查看变量的类型 ...