鱼C论坛

 找回密码
 立即注册
查看: 3746|回复: 17

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

[复制链接]
发表于 2015-5-2 11:35:37 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
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.

If BaiduShurufa_2015-5-2_11-33-58.png represents the nth digit of the fractional part, find the value of the following expression.

BaiduShurufa_2015-5-2_11-31-32.png

题目:

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

0.123456789101112131415161718192021...

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

如果用 BaiduShurufa_2015-5-2_11-33-58.png 表示这个数小数部分的第 n 位,找出如下表达式的值:

BaiduShurufa_2015-5-2_11-31-32.png



想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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;
}
//获取一个数的第几位
//从左边开始第几个
int  getnum(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;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[int(str_2)])
      str_2 += '0'
print(count)
结果210
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-4 12:32:31 | 显示全部楼层
210
[Finished in 0.4s]
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[10**j-1])
print (cal)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[10**i])
    print(result)
if __name__ == '__main__':
    start = time() 
    euler040()
    print('cost %.6f sec' % (time() - start))

210
cost 0.120103 sec
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-5-21 22:12:09 | 显示全部楼层
大神们大部分都是遍历1000000
我觉得先分析了一波ps输出格式抄袭了渡风大神一波,前面很多题也感谢渡风大神给我的灵感

此代码使用matlab编程
该问题所用时间为0.007945秒
该问题的答案为210
function Output = champernownesConstant_40(Input)
tic
if nargin == 0
    Input = [100,1000,10000,100000,1000000];
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 = [9,189,2889,38889,488889,1088889];
Num = 1;
for ii = 1:length(Input)
    s = find(list>Input(ii));
    %s(1) - 1 = [1 2 3 4 5]
    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)])
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

感觉招式被偷了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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 = [1 2 3 4 5 6].*[9 90 900 9000 90000 900000];
boundary = cumsum(boundary);              %找出位数的边界
Set = [10 100 1000 10000 100000 1000000];

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
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-29 11:01:58 | 显示全部楼层
strTemp = ""
for i in range(1, 200000):
    strTemp += str(i)

product = 1
for n in [1, 10, 100, 1000, 10000, 100000, 1000000]:
    product *= int(strTemp[n-1])

print(product)
210
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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)[num - count - 1]

print("结果是:{}\n用时:{} 秒".format(
    functools.reduce(lambda x, y: x*y, [int(i) for i in map(get_str, [10**i for i in range(7)])]),
    time.process_time()))
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-7-21 16:02:13 | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2021-3-6 12:39 编辑
ZERO_ACSII = ord('0')
func = lambda x : ord(digits[x]) - ZERO_ACSII
digits = [None]
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))
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-10 17:06:46 | 显示全部楼层
210

Process returned 0 (0x0)   execution time : 0.034 s
Press any key to continue.
参考了6#的解法,先确定每个位数所在的自然数区间,再求出偏移量,取余可以确定具体取那一位
位数和通项公式

                               
登录/注册后可看大图
#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[n - 1 - digit];
}

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[j] && i < dgt[j+1]) {cur_dgt = j+1; break;}//落在哪一区间
    int t = i - dgt[cur_dgt-1] - 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;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[0]) , int(n[9]) , int(n[99]) , int(n[999]),int(n[9999]) ,int(n[99999]) , int(n[999999]))
print(int(n[0]) * int(n[9]) * int(n[99]) * int(n[999]) * int(n[9999]) * int(n[99999]) * int(n[999999]))
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-3-19 20:26:16 | 显示全部楼层
#include <stdio.h>
#include <string.h>

main()
{
        char str[1000010], temp[128];
        int i = 1, count = 1;
        str[0] = '1';
        str[1] = '\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[i - 1]);

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


210
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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
    return  int(str1[n-1])

#计算
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))
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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]记录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[i] >= k)
      break;
    nCount += f[i];
  }
  k -= nCount;//计算k在i位数中的位置
  int n = g[i] + k / i - 1, m = k % i;//计算出具体的数
  //输出具体的数字
  char str[12];
  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[nL - 1] - 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;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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[10 ** j]))
    product *= int(d_n[10 ** j])

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
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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>())
}
测试
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_cb() {
        assert_eq!(cb(1), 9);
        assert_eq!(cb(2), 189);
    }
    #[test]
    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));
    }
    #[test]
    fn test_d() {
        assert_eq!(d(1), 1);
        assert_eq!(d(12), 1);
        assert_eq!(d(13), 1);
        assert_eq!(d(100), 5);
    }
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-29 01:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表