24小时热门版块排行榜    

查看: 2452  |  回复: 19

holmescn

金虫 (正式写手)

[交流] Euler 工程 第廿四题:全排列的第100万项 已有5人参与

一个排列是一组对象的一个有序排列。比如3123是数字1、2、3和4的一个可能的排列。如果把所有的排列按照其数字or字母的大小顺序都列出来,那就成为一个全排列。比如0、1、2的全排列是:
012 021 102 120 201 210

那么,数字0、1、2、3、4、5、6、7、8和9的全排列的第100万项是多少?
回复此楼

» 猜你喜欢

» 本主题相关价值贴推荐,对您同样有帮助:

已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

huycwork

金虫 (著名写手)

★ ★ ★ ★ ★ ★
小木虫(金币+0.5):给个红包,谢谢回帖
微尘、梦想(金币+5): 鼓励交流~~ 2011-06-10 21:51:26
C++蛮力版代码:
CODE:
#include
#include
#include
using namespace std;

bool next_digit(char *first, char *last, char *end){
        char *left, *right;
        if(last-first<2){
                return false;
        }
        for(right = last; right > first; --right){
                for(left = right-1; left >= first; --left){
                        if(*left < *right){
                                if(!next_digit(left+1, right, end)){
                                        swap(*left, *right);
                                        sort(left+1, end);
                                        return true;
                                }else
                                        return true;
                        }
                }
        }
        return false;
}

string eular24(const string &str){
        char *base = const_cast(str.c_str());
        for(size_t i = 1; i < 1000000; ++i)
                next_digit(base, base+str.length()-1, base+str.length());
        return str;
}

int main(){
        cout<         return 0;
}

漩涡的中心有一块空地,空空的。
2楼2011-06-10 11:45:00
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

huycwork

金虫 (著名写手)

★ ★ ★ ★
小木虫(金币+0.5):给个红包,谢谢回帖
微尘、梦想(金币+3): 谢谢分享~~ 2011-06-10 21:51:54
非蛮力版也有,不过不是自己想出来的,就不好意思直接贴代码了,基本想法就是数制的扩展:
二进制数制是这个样子:
a1*2^n+a2*2^(n-1)+...+an*2^1+a*2^0
十进制数制是这样子:
b1*10^n+b2*10^(n-1)+...+bn*10^1+b*10^0
那我们可以考虑阶乘进制:
c1*n!+c2*(n-1)!+...+cn*1!+c*0!
不过阶乘有点问题就是1!是1,0!是0,那就失去了最后一个的意义,所以最后一个去掉:
c1*n!+c2*(n-1)!+...+cn*1!+c
那前面的6个数就依次是:
0=0*2!+0*1!+0 => 012
1=0*2!+1*1!+0 => 021
2=1*2!+0*1!+0 => 102
3=1*2!+1*1!+0 => 120
4=2*2!+0*1!+0 => 201
5=2*2!+1*1!+0 => 210
上面的计算当然跟一般的进制计算不同,一般的进制计算是要求前面的数不能大过模数,二进制的前缀只能是0和1,十进制的前缀只能是0~9,而阶乘进制的前缀就只能是0~n,n是指后面的n!,以3=>120为例,前面的运算应该是这样子:
2!:012,前缀就是take out的索引,例子的是1
1!:02,例子中的是1,拿走的就是2
0!:0,剩下来的没得选择,这也是每个末尾都是0的原因
组合起来就是120
漩涡的中心有一块空地,空空的。
3楼2011-06-10 12:04:56
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

wangww2011

木虫 (著名写手)

★ ★ ★ ★ ★ ★
小木虫(金币+0.5):给个红包,谢谢回帖
微尘、梦想(金币+5): 鼓励交流~~ 2011-06-10 21:52:10
c语言非蛮力版
当时就乱写了个 也不清楚和上面的算法一样不一样
CODE:
#include
#include


char *euler24(int n){
        int a[10],i,j,i0;
        a[0]=1;
        for(i=1;i<10;i++)a[i]=a[i-1]*(i+1);

        for(i=0;i<10;i++){
                if(a[i]>=n){
                        i0=i+1;break;
                }
        }

        int b[i0];
        for(i=i0-2;i>=0;i--){
                b[i]=n/a[i];
                n%=a[i];
                if(n==0){
                        b[i]--;
                        n=a[i];
                }
        }  

        int p[i0];
        char str[i0+1];
        for(i=0;i
        for(i=0;i                 str[i]=p[b[i0-i-2]]+48;
                for(j=b[i0-i-2];j                         p[j]=p[j+1];
     
        }
        str[i0-1]=p[0]+48;
        str[i0]='\0';

        return strdup(str);
}


int main(void){

        printf("%s\n",euler24(1000000));

        return 0;
}

[ Last edited by wangww2011 on 2011-6-10 at 13:28 ]
4楼2011-06-10 13:24:31
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

libralibra

至尊木虫 (著名写手)

骠骑将军

★ ★ ★ ★ ★
小木虫(金币+0.5):给个红包,谢谢回帖
微尘、梦想(金币+4): 鼓励交流~~ 2011-06-10 21:52:28
python偷懒版
CODE:
# 2783915460
# Elapsed time: 0.35266074 seconds

import itertools
from mytictoc import tic, toc

tic()
m=itertools.permutations('0123456789')

for i in xrange(1000000-1):
    m.next()

print ''.join(list(m.next()))
toc()

matlab/VB/python/c++/Java写程序请发QQ邮件:790404545@qq.com
5楼2011-06-10 14:58:47
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

fatpig8832

铁杆木虫 (著名写手)

★ ★ ★ ★
小木虫(金币+0.5):给个红包,谢谢回帖
微尘、梦想(金币+3): 欢迎参与~~ 2011-06-10 21:52:46
此题改小一点可以做初中或小学奥数题了...

10!=3628800, 10!/10=362880
1000000/362880=2.75------(0123456789)第一位是2
1000000-362880*2=274240
362880/9=40320
274240/40320=6.80------(013456789)第二位是7
274240-40320*6=32320
40320/8=5040
32320/5040=6.40------(01345689)第三位是8
32320-5040*6=2080
5040/7=720
2080/720=2.89------(0134569)第四位是3
2080-720*2=640
720/6=120
640/120=5.33------(014569)第五位是9
640-120*5=40
120/5=24
40/24=1.67------(01456)第六位是1
40-24*1=16
24/4=6
16/6=2.67------(0456)第七位是5
16-6*2=4
6/3=2
4/2=2------(046)第八位是4
此处已实现整除,后三位必为4开头的最大数,即460.

所以最后结果为 2783915460...
6楼2011-06-10 15:50:03
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

libralibra

至尊木虫 (著名写手)

骠骑将军

★ ★
小木虫(金币+0.5):给个红包,谢谢回帖
dubo(金币+1): 欢迎常来程序语言版讨论 2011-06-13 19:33:20
引用回帖:
Originally posted by fatpig8832 at 2011-06-10 15:50:03:
此题改小一点可以做初中或小学奥数题了...

10!=3628800, 10!/10=362880
1000000/362880=2.75------(0123456789)第一位是2
1000000-362880*2=274240
362880/9=40320
274240/40320=6.80------(013456789) ...

此法甚妙,一开始除362880的1000000是怎么来的?解释下,谢谢了
matlab/VB/python/c++/Java写程序请发QQ邮件:790404545@qq.com
7楼2011-06-10 16:21:24
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

holmescn

金虫 (正式写手)

★ ★ ★
微尘、梦想(金币+3): 鼓励交流~~ 2011-06-10 21:53:27
晕,发晚了


楼上怎么没人帖答案和时间了?

我的想法是利用阶乘直接算。因为一个全排列,其实就是每个元素都要在一个位置上出现一次。这样一共有n!个排列(这个地球人都知道)。
这样,如果某一位确定了的话,那么其余的位再用其余的数全排列就行了。(这话怎么这么绕口)

已经知道10!=3628800,9!=362880,这样1000000 - 2*9! = 274240, 也就是说第一位取0,1都不够数,取2,而后面的没的完成全排列就够100万了。OK,第一位是2了。
下面列表:

8! = 40320  274240 - 6 * 8! = 32320 第2位:7
7! = 5040   32320  - 6 * 7! = 2080  第3位:8
6! = 720    2080   - 2 * 6! = 640   第4位:3
5! = 120    640    - 5 * 5! = 40    第5位:9
4! = 24     40     - 1 * 4! = 16    第6位:1
3! = 6      16     - 2 * 3! = 4     第7位:5
2! = 2      4      - 2 * 2! = 0

最后剩:0 4 6 这三个数了. 而最后一个余0了。也就是第2个排列正好就够第100万个了.这样结果就是:2783915460

不知道结果是不是对。这个用时当然很少的了。
8楼2011-06-10 17:09:02
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

fatpig8832

铁杆木虫 (著名写手)


小木虫(金币+0.5):给个红包,谢谢回帖
引用回帖:
Originally posted by libralibra at 2011-06-10 16:21:24:
此法甚妙,一开始除362880的1000000是怎么来的?解释下,谢谢了

这个...不就是题目中的一百万吗...不过这不是编程而是死算,初中生甚至小学生都能搞出来...

8楼的做法应该和我的一样吧,虽然我没怎么看懂...
9楼2011-06-10 17:32:00
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

holmescn

金虫 (正式写手)

★ ★ ★
微尘、梦想(金币+3): 鼓励交流~~ 2011-06-10 21:53:45
python版代码,算法刚才解释过了。
CODE:
def fac(n):
    return reduce(lambda x, y: x*y, range(1, n+1))

n = 1000000
i = 9
numbers = range(10)
result = []

while i > 0 and n > 0:
    if n % fac(i) != 0:
        result.append(numbers[n/fac(i)])
    else:
        result.append(numbers[n/fac(i)-1])
    numbers.remove(result[-1])
    n  = n % fac(i)
    i -= 1

if len(numbers) > 0:
    numbers.reverse()
    result.extend(numbers)

print "".join([str(x) for x in result])

[ Last edited by holmescn on 2011-6-11 at 07:58 ]
10楼2011-06-10 18:03:37
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
相关版块跳转 我要订阅楼主 holmescn 的主题更新
普通表情 高级回复 (可上传附件)
最具人气热帖推荐 [查看全部] 作者 回/看 最后发表
[基金申请] 中青基了要发朋友圈吗? +7 349506619 2026-08-28 7/350 2026-08-31 13:39 by 冼亮淀粉酶
[基金申请] 29号明天会评吗 +4 笨笨唐 2026-08-28 4/200 2026-08-31 09:30 by huixian257
[基金申请] 国社科又开始会评了,不知道这次命运如何 +6 雨打竹帘 2026-08-30 10/500 2026-08-31 09:29 by huixian257
[基金申请] 基金不中,共勉 +12 eulota 2026-08-26 12/600 2026-08-31 08:42 by ZJTJZ
[基金申请] 能否申诉? +6 echo8914667 2026-08-30 7/350 2026-08-31 08:41 by kingkocxr
[考博] 找导师 +6 yuanjiabao 2026-08-29 7/350 2026-08-30 14:40 by 生科新手
[基金申请] 麻烦专家们看看评委们的意见(F口面上) +6 gdd2018 2026-08-28 11/550 2026-08-30 08:58 by 超级无敌华子
[基金申请] 我就是申请一个面上项目而已,这评审意见是按照杰青的条件评的吧? +6 gouxfjh 2026-08-28 11/550 2026-08-30 07:57 by gouxfjh
[基金申请] 2026年叶企孙基金 +4 bud_bud 2026-08-27 7/350 2026-08-29 07:23 by foolishmani
[基金申请] 为什么资助数各大高校都创新高,自己申请怎么就这么难 +12 Kittylucky 2026-08-27 13/650 2026-08-29 00:04 by superceng
[基金申请] 怎么查啊 +6 huang1991js 2026-08-26 6/300 2026-08-28 08:42 by winsaint
[基金申请] 哪位高人中了,把查询到的截图贴出来让我看看,让我长长见识 +5 yuleib84 2026-08-26 6/300 2026-08-28 00:02 by yudaoqian88
[基金申请] 基金未中,这种答复是模板吗? +5 zhaosm1982 2026-08-27 6/300 2026-08-27 16:00 by lfy8008
[基金申请] 看板上这么多中的,有点像50人群里49个人都是骗子的那种感觉…… +5 a089 2026-08-26 6/300 2026-08-27 14:05 by jonewore
[基金申请] 我不理解! +15 Edward_pc 2026-08-26 23/1150 2026-08-26 20:34 by zzuzxg
[基金申请] 出来了 +9 trojank 2026-08-26 9/450 2026-08-26 14:25 by 宝贝虫子
[基金申请] 为什么国自然不能直接公布 +4 bjdxyxy 2026-08-26 4/200 2026-08-26 13:12 by qingmu1201
[基金申请] 项目信息和经费信息在系统里都可以看到了 +6 wittyboy 2026-08-26 14/700 2026-08-26 10:55 by wittyboy
[基金申请] 在坚冰还盖着北海的时候,我看到了怒放的梅花。 (金币+10) +6 ziyangfang 2026-08-25 9/450 2026-08-25 20:26 by huagongfeihu
[基金申请] 某些机构,以效率低为荣,以效率低作为存在感 +9 yuleib84 2026-08-25 10/500 2026-08-25 17:14 by alexon
信息提示
请填处理意见