欧拉计划 发表于 2015-5-2 11:35:37

题目40:找出这个无理数的小数部分的第n位

Champernowne's constant

An irrational decimal fraction is created by concatenating the positive integers:

0.123456789101112131415161718192021...

It can be seen that the 12th digit of the fractional part is 1.

Ifrepresents the nth digit of the fractional part, find the value of the following expression.


题目:

将正整数连接起来可以得到一个无理小数:

0.123456789101112131415161718192021...

可以看出小数部分的第 12 位是 1。

如果用表示这个数小数部分的第 n 位,找出如下表达式的值:





迷雾少年 发表于 2016-8-30 13:44:24

210。。不知道对否
#include <iostream>
using namespace std;
//获取一个int类型的位数
int get(int n)
{
        if(n==0) return 1;
        int m = 0;
        while (n)
        {
                n/=10;
                m++;
        }
        return m;
}
//获取一个数的第几位
//从左边开始第几个
intgetnum(int n,int m)
{
        int k = get(n)-m+1; //就是右边的k个
        int z = 1;
        while (n)
        {
                if(z==k)
                        return n%10;
                n/=10;

                z++;

        }
}
int main(void)
{

        int j=0;//第几位
        int z = 0;
        int result = 1;

        for (int i =1;i<1000000;i++)
        {
                z=get(i);
                for (int k=j+1;k<=j+z;k++)
                {
                          if(k==10 || 100==k || 1000==k || 10000==k || 100000==k|| 1000000==k)
                          {
                                   result*=getnum(i,k-j);
                          }
               
                }
                j+=z;
               
       
        }
        std::cout<<result;
        return 0;
}

愤怒的大头菇 发表于 2016-9-6 22:47:44

str_1 = '0'
for i in range(1,1000000):
      str_1 += str(i)
str_2 = '1'
count = 1
for i in range(7):
      count *= int(str_1)
      str_2 += '0'
print(count)
结果210

jerryxjr1220 发表于 2016-10-4 12:32:31

210


def getstr(n):
        strlist = '1'
        for i in range(2,n+1):
                strlist += str(i)
        return strlist
strlist = getstr(200000)
cal = 1
for j in range(7):
        cal *= int(strlist)
print (cal)

芒果加黄桃 发表于 2017-1-15 10:16:49

# encoding:utf-8
# 小数后第N位相乘
from time import time
def euler040():
    s_tmp = '.'
    result = 1
    for i in range(1,200000):
      s_tmp += str(i)
      if len(s_tmp) > 1000000:
            break
    for i in range(0,7):
      result *= int(s_tmp)
    print(result)
if __name__ == '__main__':
    start = time()
    euler040()
    print('cost %.6f sec' % (time() - start))


210
cost 0.120103 sec

loadinggg 发表于 2017-5-21 22:12:09

大神们大部分都是遍历1000000
我觉得先分析了一波ps输出格式抄袭了渡风大神一波,前面很多题也感谢渡风大神给我的灵感

此代码使用matlab编程
该问题所用时间为0.007945秒
该问题的答案为210
function Output = champernownesConstant_40(Input)
tic
if nargin == 0
    Input = ;
end
%想找到各个位置上的数字,不用全部写出来,只需要计算位数就可以
%个位数1-9,十位数10-99,百位数100-999,千位数1000-9999,万位数10000-99999,十万位数100000-999999
%上述的数字个数一共是9+90*2+900*3+9000*4+90000*5+100000*6 = 1088889位数
%先判断出Input中的数是属于哪两个位数之间的,然后根据低位数的第几个判断出来第几个数
%第一位和第十位都是1
list = ;
Num = 1;
for ii = 1:length(Input)
    s = find(list>Input(ii));
    %s(1) - 1 =
    a = floor((Input(s(1)-1) - list(s(1)-1))/s(1));%低位数的第几个数-1
    b = mod((Input(s(1)-1) - list(s(1)-1)),s(1));
    qianshu = a + 10^(ii) - 1;
    if b == 0
      res = num2str(qianshu);
      Num = Num * str2num(res(end));
    else
      zhenshu = qianshu + 1;
      res = num2str(zhenshu);
      Num = Num * str2num(res(b));
    end
end
Output = Num;
toc
disp('此代码使用matlab编程')
disp(['该问题所用时间为',num2str(toc),'秒'])
disp(['该问题的答案为',num2str(Output)])

渡风 发表于 2017-6-12 20:16:47

loadinggg 发表于 2017-5-21 22:12
大神们大部分都是遍历1000000
我觉得先分析了一波ps输出格式抄袭了渡风大神一波,前面很多题也感谢渡风大 ...

感觉招式被偷了{:5_90:}

渡风 发表于 2017-6-12 20:17:48

此代码使用matlab编程
Problem40所用时间为0.0063565秒
Problem40的答案为210
编程思路与楼上一致。
%% Problem40.m
%最后编辑时间:2017-06-12 19:11 版本1.0
%将正整数连接起来可以得到一个无理小数: 0.123456789101112131415161718192021...
%求第1,10,100,1000,10000,100000,1000000,的乘积
function Output = Problem40()
tic
boundary = .*;
boundary = cumsum(boundary);            %找出位数的边界
Set = ;

Output = 1;
for ii = 1:6
    Temp = Set(ii);
    for jj = 1:length(Set)
      if boundary(jj) < Temp && Temp <= boundary(jj+1)   %预测在哪个位置
            Start = jj;            
            break
      end
    end
   
    Distance = Set(ii) - boundary(Start);
    Num = floor(Distance / (Start + 1));
    Numset = mod(Distance,Start + 1);
   
    All= 10^Start : 10^(Start + 1);
   
    if Numset == 0
      Exact = num2str(All(Num));
      Output = Output * str2double(Exact(end));
    else
      Exact = num2str(All(Num+1));      
      Output = Output * str2double(Exact(Numset));
    end
      
end
   
toc

disp('此代码使用matlab编程')
disp(['Problem40所用时间为',num2str(toc),'秒'])
disp(['Problem40的答案为',num2str(Output)])
end

k往事如烟k 发表于 2019-3-29 11:01:58


strTemp = ""
for i in range(1, 200000):
    strTemp += str(i)

product = 1
for n in :
    product *= int(strTemp)

print(product)
210

王小召 发表于 2019-6-14 13:44:15

结果是:210
用时:0.2652017 秒
import functools
import time

def get_str(num):
    count = 0
    tmp = 0
    while count < num:
            tmp += 1
            count += len(str(tmp))
    return str(tmp)

print("结果是:{}\n用时:{} 秒".format(
    functools.reduce(lambda x, y: x*y, )]),
    time.process_time()))

永恒的蓝色梦想 发表于 2019-7-21 16:02:13

本帖最后由 永恒的蓝色梦想 于 2021-3-6 12:39 编辑

ZERO_ACSII = ord('0')
func = lambda x : ord(digits) - ZERO_ACSII
digits =
i = 1


while len(digits) <= 1000000:
    digits += str(i)
    i += 1


print(func(1) * func(10) * func(100) * func(1000) * func(10000) * func(100000) * func(1000000))

debuggerzh 发表于 2020-8-10 17:06:46

210

Process returned 0 (0x0)   execution time : 0.034 s
Press any key to continue.
参考了6#的解法,先确定每个位数所在的自然数区间,再求出偏移量,取余可以确定具体取那一位
位数和通项公式
https://wx3.sinaimg.cn/mw690/0081qlg6ly1ghltrk2iujj30nm00swea.jpg
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;

const int dgt[] = {0,9,189,2889,38889,488889,5888889};//0为占位符
const int M = 1000000;

int extract(int x,int digit){
vector<int> v;
while(x){
    v.push_back(x % 10);
    x /= 10;
}
int n = v.size();
return v;
}

int main(){
int ans = 1;

for (int i = 10;i <= M;i*=10){
    int cur_dgt;
    for (int j = 1;j < 6;j++)
      if (i > dgt && i < dgt) {cur_dgt = j+1; break;}//落在哪一区间
    int t = i - dgt - 1;
    int cnt = t / cur_dgt;//偏移了cnt个数
    int resd = t % cur_dgt;//取该数的第几位
    int tar = i/10 + cnt;//目标数
    //printf("%d %d %d %d %d\n",t,cur_dgt,cnt,tar,resd);
    ans *= extract(tar,resd);

}
cout << ans << endl;
return 0;
}

4444567 发表于 2020-10-11 12:42:42

1000005 185186
1 1 5 3 7 2 1
210

n = ''
a = 1
while len(n) < 1000001:
    n += str(a)
    a += 1
   
print(len(n),a)
print(int(n) , int(n) , int(n) , int(n),int(n) ,int(n) , int(n))
print(int(n) * int(n) * int(n) * int(n) * int(n) * int(n) * int(n))

a1351468657 发表于 2021-3-19 20:26:16

#include <stdio.h>
#include <string.h>

main()
{
        char str, temp;
        int i = 1, count = 1;
        str = '1';
        str = '\0';

        for (i = 2; i < 1000000; i++)
        {
                if (count >= 1000000)
                {
                        break;
                }
                sprintf(temp, "%d", i);
                count += strlen(temp);
                strcat(str, temp);                       
        }
        count = 1;
        for (i = 1; i < 1000001; i *= 10)
        {
                printf("%c ", str);

                count *= (str - '0');
        }
        printf("\n%d\n", count);
}


210

ft215378 发表于 2021-10-21 13:10:29

#找出这个无理数的小数部分的第n位
from time import *
#简单计算得出当数字在19万以内 位数超过百万
def d(n):
    str1 = ''
    num = 1
    while True:
      str1 += str(num)
      num += 1
      if num == 190000:
            break
    returnint(str1)

#计算
start = time()
n = 1
result = 1
while n:
    result *= d(n)
    n *= 10
    if n == 1000000:
      break

end = time()
print(result)
print("用时:%.4f秒" % (end-start))

guosl 发表于 2022-1-6 21:11:30

本帖最后由 guosl 于 2022-1-6 21:18 编辑

#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;

int f[] = { 0,9,2 * 90,3 * 900,4 * 9000,5 * 90000,6 * 900000 };//f记录i位数的个数
int g[] = { 0,1,10,100,1000,10000,100000 };//记录i位数的第一个数

int getDigit(int k)
{
int nCount = 0, i;
for (i = 1; i <= 6; ++i)//找出k是几位数
{
    if (nCount + f >= k)
      break;
    nCount += f;
}
k -= nCount;//计算k在i位数中的位置
int n = g + k / i - 1, m = k % i;//计算出具体的数
//输出具体的数字
char str;
int nL;
if (m == 0)
{
    _itoa_s(n, str, 10);
    nL = strlen(str);
}
else
{
    _itoa_s(n + 1, str, 10);
    nL = m;
}
return int(str - 48);
}

int main(void)
{
int p = getDigit(1);
p *= getDigit(10);
p *= getDigit(100);
p *= getDigit(1000);
p *= getDigit(10000);
p *= getDigit(100000);
p *= getDigit(1000000);
cout << p << endl;
return 0;
}

B1tetheDust 发表于 2022-10-24 18:56:23

import time as t

start = t.perf_counter()
d_n = ''
for i in range(185186):
    d_n += str(i)

product = 1
for j in range(7):
    print('d_%d = %s' % (10 ** j, d_n))
    product *= int(d_n)

print(product)
print("It costs %f s" % (t.perf_counter() - start))



d_1 = 1
d_10 = 1
d_100 = 5
d_1000 = 3
d_10000 = 7
d_100000 = 2
d_1000000 = 1
210
It costs 0.067895 s

mathtimes 发表于 2023-10-20 16:55:35

$ time ./main
210

real        0m0.001s
user        0m0.000s
sys        0m0.001s
// count bits before 10^l
fn cb(l: u32) -> u32 {
    if l == 0 {
      return 0;
    }
    9 * 10u32.pow(l - 1) * l + cb(l - 1)
}

// 返回第i位所在的数字以及偏移量
fn b2n(x: u32) -> (u32, u32) {
    let mut base_l = 1;
    while cb(base_l) < x {
      base_l += 1;
    }
    base_l -= 1;
    (
      (x - cb(base_l)) / (base_l + 1) + 10u32.pow(base_l) - 1,
      (x - cb(base_l)) % (base_l + 1),
    )
}

fn d(x: u32) -> u32 {
    let (b, mut i) = b2n(x);
    if i == 0 {
      return b % 10;
    }
    let mut y = b + 1;
    i = y.ilog10() + 2 - i;
    let mut r = 0;
    while i > 0 {
      r = y % 10;
      y /= 10;
      i -= 1;
    }
    r
}
fn main() {
    println!("{}", (0..=6).map(|x| d(10u32.pow(x))).product::<u32>())
}
测试
#
mod tests {
    use super::*;
    #
    fn test_cb() {
      assert_eq!(cb(1), 9);
      assert_eq!(cb(2), 189);
    }
    #
    fn test_b2n() {
      assert_eq!(b2n(8), (8, 0));
      assert_eq!(b2n(9), (9, 0));
      assert_eq!(b2n(100), (54, 1));
      assert_eq!(b2n(189), (99, 0));
      assert_eq!(b2n(191), (99, 2));
      assert_eq!(b2n(192), (100, 0));
    }
    #
    fn test_d() {
      assert_eq!(d(1), 1);
      assert_eq!(d(12), 1);
      assert_eq!(d(13), 1);
      assert_eq!(d(100), 5);
    }
}
页: [1]
查看完整版本: 题目40:找出这个无理数的小数部分的第n位