免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: DNFCF
打印 上一主题 下一主题

[算法] 变态的算法题 [复制链接]

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:45
41 [报告]
发表于 2011-05-04 23:35 |只看该作者
smilence

论坛徽章:
1
天秤座
日期:2014-04-27 07:42:20
42 [报告]
发表于 2011-05-05 17:04 |只看该作者
本帖最后由 A.com 于 2011-05-05 17:30 编辑

刚才看到有人说二叉树不给用递归,想起来这个数字的变化其实是可预期的,譬如把某位的0变成1,那么整个数字就是N+1,无论这个0在什么位置,他变成1的结果都是相同的。也就是说只有组合相关性没有排列相关性。又因为这21位数里面至少要有一位是9(没有9的组合不可能大于10^20),所以实际需要遍历的总次数是10个数字的20位组合减去9个以上9的组合{:3_190:}


最暴力的办法就是写就是20层循环,前8层0-9,后12层0-8,最里面别忘了加上一个9^21。才282529536481次循环就行了,

论坛徽章:
0
43 [报告]
发表于 2011-05-05 18:06 |只看该作者
没有9的组合不可能大于10^20

11 * 8^21= 101,457,092,405,402,533,888

论坛徽章:
1
天秤座
日期:2014-04-27 07:42:20
44 [报告]
发表于 2011-05-06 08:38 |只看该作者
11 * 8^21= 101,457,092,405,402,533,888
KBTiller 发表于 2011-05-05 18:06



    呃,算错了。。{:3_185:}

论坛徽章:
2
水瓶座
日期:2013-09-04 15:09:57白羊座
日期:2014-04-17 16:48:13
45 [报告]
发表于 2011-05-06 20:14 |只看该作者
本帖最后由 l2y3n2 于 2011-05-06 20:16 编辑

随便用Python写了个穷举的,用时间正好3分钟、Python自带的大数运算、程序也没有优化过。
就是穷举9、8、7、……、0的个数,然后对比结果。

用C的话时间上应该还是没问题的

~$ time ./f.py
449177399146038697307
128468643043731391252

real    2m54.915s
user    2m54.871s
sys     0m0.012s

  1. #! /usr/bin/env python
  2. # -*- coding: UTF-8 -*-

  3. def check(value, nums):
  4.     tmp = [0] * 10
  5.     for c in str(value):
  6.         tmp[ord(c) - ord('0')] += 1
  7.     for i in range(0, 10):
  8.         if tmp[i] != nums[i]:
  9.             return False
  10.     return True


  11. def action(exps, nums, n, leftn, value, idx):
  12.     value += exps[idx] * leftn
  13.     nums[idx] = leftn
  14.     if len(str(value)) < n:
  15.         return

  16.     if (idx == 0):
  17.         if (check(value, nums)):
  18.             print(value)
  19.         return

  20.     for i in range(0, leftn + 1):
  21.         if len(str(value)) <= n:
  22.             action(exps, nums, n, leftn - nums[idx], value, idx - 1)
  23.         value -= exps[idx]
  24.         nums[idx] -= 1


  25. def main(n):
  26.     exps = [i ** n for i in range(0, 10)]
  27.     nums = [0] * 10
  28.     action(exps, nums, n, n, 0, 9)


  29. if __name__ == '__main__':
  30.     main(21)


复制代码

论坛徽章:
0
46 [报告]
发表于 2011-05-13 13:10 |只看该作者
用了40多秒
KBTiller 发表于 2011-05-03 22:07



    想请问你具体怎么做的?我想的是对21位数进行枚举,但是那样很崩溃,太慢了

论坛徽章:
0
47 [报告]
发表于 2011-05-13 20:32 |只看该作者
本帖最后由 KBTiller 于 2011-05-19 10:34 编辑
想请问你具体怎么做的?我想的是对21位数进行枚举,但是那样很崩溃,太慢了
oiacm 发表于 2011-05-13 13:10



    基本是按照10楼的那种思路做的
    只对21位数的各种组合验算
    提供组合大体上是这样实现的

    选择某位数字( 1 , 1 );    //选第1位数字,从1开始


void 选择某位数字(const int 第几位 , const  int 起始的数字 )
{
    if (  第几位 >  21  ){
        //验算
        return ;
    }   
    for (int 数字 = 起始的数字 ; 数字 < 10 ; 数字 ++  ){
        选择某位数字 ( 第几位 + 1 , ( 第几位 == 1 ? 0 : 数字 )  ) ;  //第2位及以后各位从0开始选择  
    }   
}

   就是第一位1~9。第二位及以后都从0开始选数字,但要保证第二位以后是个有序的数字序列

   此外用到了:各个数字的21次方事先计算好,以后查表计算各个数字的21次方的和;9的个数不能太多

   我过几天会把详细的解法写出来
==============================
这个有点聪明反被聪明误了
最初,并没有考虑第一位不可以为0
但这样多了一个21位都为0的情况
为了表达的更自然
后来改进成第一位不能为0
后面各位有序
但这样实际上多了若干重复的组合(见41楼)

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:11数据库技术版块每日发帖之星
日期:2015-08-30 06:20:00
48 [报告]
发表于 2011-05-14 02:17 |只看该作者
晕死,这里哪有用到乘法啊,分明就只有加法。

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:11数据库技术版块每日发帖之星
日期:2015-08-30 06:20:00
49 [报告]
发表于 2011-05-14 02:20 |只看该作者
我给个思路吧。

不用去算数。

char N[21]

用循环的方式。

先计算 21 一个 1 的结果,
然后是  20 个 1 , 一个 2 ...
依次类推

在每次便利中,寻找一个可能的 21 个数字的排序使得结合的大叔是一样大的。

大数用 long long 就可以表示了吧?

论坛徽章:
3
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:11数据库技术版块每日发帖之星
日期:2015-08-30 06:20:00
50 [报告]
发表于 2011-05-14 02:21 |只看该作者
利用  99 乘法表,直接查表不通过计算。

晕死,我马上写一个,我对这个数字的确切大小非常感兴趣。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP