码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4937 Lucky Number 搜索

时间:2014-08-14 23:42:56      阅读:334      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   for   ar   

题意:

  给你一个数,求在多少种不同的进制下这个数每一位都是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]的因子就好了。

  代码如下:

bubuko.com,布布扣
  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 }
View Code

 

    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 。所以就不会超时了。

  代码如下:

bubuko.com,布布扣
  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 const int INF = 1<<30;
 20 
 21 ll n;
 22 int ans;
 23 
 24 inline int function1(ll a, ll b) { //n = a*base + b
 25     if (((n-b)%a)!=0) return 0; //如果不是整数
 26     ll tmp = (n-b)/a;
 27     if (a>=tmp || b>=tmp) return 0; //如果位数大于进制数
 28     return 1;
 29 }
 30 
 31 inline int function2(ll a, ll b, ll c) { //n = a*base^2 + b*base + c
 32     c -= n;
 33     ll t1 = b*b-4*a*c;
 34     if (t1<0) return 0;
 35     ll t2 = (ll) sqrt((double)t1);
 36     if (t2*t2!=t1) return 0;
 37     if (((t2-b)%(2*a))!=0) return 0;
 38     t1 = (t2-b)/2/a;
 39     if (t1<=a || t1<=b || t1<=c || t1<=0) return 0;
 40     return 1;
 41 }
 42 
 43 inline bool check(int base) {
 44     ll t = n, cnt = 0, tt;
 45     while (t>0) {
 46         tt = t%base;
 47         if (!(2<tt&&tt<7)) return false;
 48         t /= base;
 49         cnt++;
 50     }
 51     return cnt>3;
 52 }
 53 
 54 void solve() {
 55     scanf("%I64d", &n);
 56 
 57     if (2<n&&n<7) {
 58         puts("-1");
 59         return ;
 60     }
 61 
 62     ans = 0;
 63     for (int i = 3; i < 7; i++) {
 64         for (int j = 3; j < 7; j++) {
 65             for (int k = 3; k < 7; k++) {
 66                 ans += function2(i, j, k);
 67             }
 68             ans += function1(i, j);
 69         }
 70     }
 71     ll len = min(n, 7000ll);
 72     for (int i = 4; i < len; i++)
 73         ans += check(i) ? 1 : 0;
 74 
 75     printf("%d\n", ans);
 76 }
 77 
 78 
 79 void ttt(int i) {
 80     int t = 255;
 81     printf("%d:", i);
 82     while (t) {
 83         printf("%d ", t%i);
 84         t /= i;
 85     }
 86     puts("");
 87 }
 88 
 89 int main() {
 90     #ifdef Phantom01
 91         freopen("HDU4937.in", "r", stdin);
 92 //        freopen("HDU4937.txt", "w", stdout);
 93     #endif //Phantom01
 94 
 95     int T;
 96     scanf("%d", &T);
 97     for (int i = 1; i <= T; i++) {
 98         printf("Case #%d: ", i);
 99         solve();
100     }
101 
102     return 0;
103 }
View Code

 

HDU 4937 Lucky Number 搜索,布布扣,bubuko.com

HDU 4937 Lucky Number 搜索

标签:style   blog   http   color   os   io   for   ar   

原文地址:http://www.cnblogs.com/Phantom01/p/3913584.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!