题意:
给你一个数,求在多少种不同的进制下这个数每一位都是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]的因子就好了。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <algorithm> 7 #include <string> 8 #include <queue> 9 #include <stack> 10 #include <vector> 11 #include <map> 12 #include <set> 13 #include <functional> 14 #include <time.h> 15 16 using namespace std; 17 18 typedef __int64 ll; 19 20 const int INF = 1<<30; 21 const int MAXN = (int) 1e6+5; 22 23 int Prime[MAXN], len; 24 bool is[MAXN]; 25 26 ll f[20]; 27 int cnt[20], num; 28 29 void factor(ll x) { //分解质因数 30 num = 0; 31 if (x==1) return ; 32 for (int i = 0; i < len; i++) if ((x%Prime[i])==0) { 33 f[num] = Prime[i]; 34 cnt[num] = 0; 35 while (x%Prime[i]==0) { 36 x /= Prime[i]; 37 cnt[num]++; 38 } 39 num++; 40 if (x==1) break; 41 if (x<Prime[len-1] && !is[x]) break; 42 } 43 if (x!=1) { 44 f[num] = x; 45 cnt[num++] = 1; 46 } 47 } 48 49 ll n; 50 int ans; 51 52 void dfs(ll base, int deep) { //枚举可以重复的组合 53 if (deep==num) { 54 if (base < 4) return ; 55 ll tmp = n, t; 56 while (tmp) { 57 t = tmp%base; 58 if (!(2<t&&t<7)) return ; 59 tmp /= base; 60 } 61 ans++; 62 return ; 63 } 64 ll tmp = base; 65 for (int i = 0; i <= cnt[deep]; i++) { 66 dfs(tmp, deep+1); 67 tmp *= f[deep]; 68 } 69 } 70 71 void solve() { 72 scanf("%I64d", &n); 73 ans = 0; 74 if (2<n&&n<7) { 75 puts("-1"); 76 return ; 77 } 78 for (int i = 3; i < 7; i++) if (n-i>10) { //枚举末位 79 factor(n-i); 80 dfs(1LL, 0); 81 } 82 printf("%d\n", ans); 83 } 84 85 int main() { 86 #ifdef Phantom01 87 freopen("HDU4937.in", "r", stdin); 88 #endif //Phantom01 89 90 memset(is, false, sizeof(is)); 91 len = 0; 92 for (int i = 2; i < MAXN; i++) if (!is[i]) { 93 Prime[len++] = i; 94 for (ll j = i*2; j < MAXN; j+=i) 95 is[j] = true; 96 } 97 98 int T; 99 scanf("%d", &T); 100 for (int i = 1; i <= T; i++) { 101 printf("Case #%d: ", i); 102 solve(); 103 } 104 105 return 0; 106 }