鱼C论坛

 找回密码
 立即注册
查看: 3421|回复: 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。。不知道对否
  1. #include <iostream>
  2. using namespace std;
  3. //获取一个int类型的位数
  4. int get(int n)
  5. {
  6.         if(n==0) return 1;
  7.         int m = 0;
  8.         while (n)
  9.         {
  10.                 n/=10;
  11.                 m++;
  12.         }
  13.         return m;
  14. }
  15. //获取一个数的第几位
  16. //从左边开始第几个
  17. int  getnum(int n,int m)
  18. {
  19.         int k = get(n)-m+1; //就是右边的k个
  20.         int z = 1;
  21.         while (n)
  22.         {
  23.                 if(z==k)
  24.                         return n%10;
  25.                 n/=10;

  26.                 z++;

  27.         }
  28. }
  29. int main(void)
  30. {

  31.         int j=0;//第几位
  32.         int z = 0;
  33.         int result = 1;

  34.         for (int i =1;i<1000000;i++)
  35.         {
  36.                 z=get(i);
  37.                 for (int k=j+1;k<=j+z;k++)
  38.                 {
  39.                           if(k==10 || 100==k || 1000==k || 10000==k || 100000==k|| 1000000==k)
  40.                           {
  41.                                    result*=getnum(i,k-j);
  42.                           }
  43.                
  44.                 }
  45.                 j+=z;
  46.                
  47.        
  48.         }
  49.         std::cout<<result;
  50.         return 0;
  51. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-9-6 22:47:44 | 显示全部楼层
  1. str_1 = '0'
  2. for i in range(1,1000000):
  3.       str_1 += str(i)
  4. str_2 = '1'
  5. count = 1
  6. for i in range(7):
  7.       count *= int(str_1[int(str_2)])
  8.       str_2 += '0'
  9. print(count)
复制代码

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

使用道具 举报

发表于 2016-10-4 12:32:31 | 显示全部楼层
210
[Finished in 0.4s]

  1. def getstr(n):
  2.         strlist = '1'
  3.         for i in range(2,n+1):
  4.                 strlist += str(i)
  5.         return strlist
  6. strlist = getstr(200000)
  7. cal = 1
  8. for j in range(7):
  9.         cal *= int(strlist[10**j-1])
  10. print (cal)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-15 10:16:49 | 显示全部楼层
  1. # encoding:utf-8
  2. # 小数后第N位相乘
  3. from time import time
  4. def euler040():
  5.     s_tmp = '.'
  6.     result = 1
  7.     for i in range(1,200000):
  8.         s_tmp += str(i)
  9.         if len(s_tmp) > 1000000:
  10.             break
  11.     for i in range(0,7):
  12.         result *= int(s_tmp[10**i])
  13.     print(result)
  14. if __name__ == '__main__':
  15.     start = time()
  16.     euler040()
  17.     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
  1. function Output = champernownesConstant_40(Input)
  2. tic
  3. if nargin == 0
  4.     Input = [100,1000,10000,100000,1000000];
  5. end
  6. %想找到各个位置上的数字,不用全部写出来,只需要计算位数就可以
  7. %个位数1-9,十位数10-99,百位数100-999,千位数1000-9999,万位数10000-99999,十万位数100000-999999
  8. %上述的数字个数一共是9+90*2+900*3+9000*4+90000*5+100000*6 = 1088889位数
  9. %先判断出Input中的数是属于哪两个位数之间的,然后根据低位数的第几个判断出来第几个数
  10. %第一位和第十位都是1
  11. list = [9,189,2889,38889,488889,1088889];
  12. Num = 1;
  13. for ii = 1:length(Input)
  14.     s = find(list>Input(ii));
  15.     %s(1) - 1 = [1 2 3 4 5]
  16.     a = floor((Input(s(1)-1) - list(s(1)-1))/s(1));%低位数的第几个数-1
  17.     b = mod((Input(s(1)-1) - list(s(1)-1)),s(1));
  18.     qianshu = a + 10^(ii) - 1;
  19.     if b == 0
  20.         res = num2str(qianshu);
  21.         Num = Num * str2num(res(end));
  22.     else
  23.         zhenshu = qianshu + 1;
  24.         res = num2str(zhenshu);
  25.         Num = Num * str2num(res(b));
  26.     end
  27. end
  28. Output = Num;
  29. toc
  30. disp('此代码使用matlab编程')
  31. disp(['该问题所用时间为',num2str(toc),'秒'])
  32. 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
编程思路与楼上一致。
  1. %% Problem40.m
  2. %最后编辑时间:2017-06-12 19:11 版本1.0
  3. %将正整数连接起来可以得到一个无理小数: 0.123456789101112131415161718192021...
  4. %求第1,10,100,1000,10000,100000,1000000,的乘积
  5. function Output = Problem40()
  6. tic
  7. boundary = [1 2 3 4 5 6].*[9 90 900 9000 90000 900000];
  8. boundary = cumsum(boundary);              %找出位数的边界
  9. Set = [10 100 1000 10000 100000 1000000];

  10. Output = 1;
  11. for ii = 1:6
  12.     Temp = Set(ii);
  13.     for jj = 1:length(Set)
  14.         if boundary(jj) < Temp && Temp <= boundary(jj+1)   %预测在哪个位置
  15.             Start = jj;            
  16.             break
  17.         end
  18.     end
  19.    
  20.     Distance = Set(ii) - boundary(Start);
  21.     Num = floor(Distance / (Start + 1));
  22.     Numset = mod(Distance,Start + 1);
  23.    
  24.     All  = 10^Start : 10^(Start + 1);
  25.    
  26.     if Numset == 0
  27.         Exact = num2str(All(Num));
  28.         Output = Output * str2double(Exact(end));
  29.     else
  30.         Exact = num2str(All(Num+1));        
  31.         Output = Output * str2double(Exact(Numset));
  32.     end
  33.         
  34. end
  35.    
  36. toc

  37. disp('此代码使用matlab编程')
  38. disp(['Problem40所用时间为',num2str(toc),'秒'])
  39. disp(['Problem40的答案为',num2str(Output)])
  40. end
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-29 11:01:58 | 显示全部楼层

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

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

  7. print(product)
复制代码

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

使用道具 举报

发表于 2019-6-14 13:44:15 | 显示全部楼层
结果是:210
用时:0.2652017 秒
  1. import functools
  2. import time

  3. def get_str(num):
  4.     count = 0
  5.     tmp = 0
  6.     while count < num:
  7.             tmp += 1
  8.             count += len(str(tmp))
  9.     return str(tmp)[num - count - 1]

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

使用道具 举报

发表于 2019-7-21 16:02:13 | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2021-3-6 12:39 编辑
  1. ZERO_ACSII = ord('0')
  2. func = lambda x : ord(digits[x]) - ZERO_ACSII
  3. digits = [None]
  4. i = 1


  5. while len(digits) <= 1000000:
  6.     digits += str(i)
  7.     i += 1


  8. 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#的解法,先确定每个位数所在的自然数区间,再求出偏移量,取余可以确定具体取那一位
位数和通项公式

                               
登录/注册后可看大图

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<vector>
  4. using namespace std;

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

  7. int extract(int x,int digit){
  8.   vector<int> v;
  9.   while(x){
  10.     v.push_back(x % 10);
  11.     x /= 10;
  12.   }
  13.   int n = v.size();
  14.   return v[n - 1 - digit];
  15. }

  16. int main(){
  17.   int ans = 1;

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

  28.   }
  29.   cout << ans << endl;
  30.   return 0;
  31. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-10-11 12:42:42 | 显示全部楼层
1000005 185186
1 1 5 3 7 2 1
210

  1. n = ''
  2. a = 1
  3. while len(n) < 1000001:
  4.     n += str(a)
  5.     a += 1
  6.    
  7. print(len(n),a)
  8. print(int(n[0]) , int(n[9]) , int(n[99]) , int(n[999]),int(n[9999]) ,int(n[99999]) , int(n[999999]))
  9. 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 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <string.h>

  3. main()
  4. {
  5.         char str[1000010], temp[128];
  6.         int i = 1, count = 1;
  7.         str[0] = '1';
  8.         str[1] = '\0';

  9.         for (i = 2; i < 1000000; i++)
  10.         {
  11.                 if (count >= 1000000)
  12.                 {
  13.                         break;
  14.                 }
  15.                 sprintf(temp, "%d", i);
  16.                 count += strlen(temp);
  17.                 strcat(str, temp);                       
  18.         }
  19.         count = 1;
  20.         for (i = 1; i < 1000001; i *= 10)
  21.         {
  22.                 printf("%c ", str[i - 1]);

  23.                 count *= (str[i - 1] - '0');
  24.         }
  25.         printf("\n%d\n", count);
  26. }
复制代码



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 编辑
  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cstring>
  4. using namespace std;

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

  7. int getDigit(int k)
  8. {
  9.   int nCount = 0, i;
  10.   for (i = 1; i <= 6; ++i)//找出k是几位数
  11.   {
  12.     if (nCount + f[i] >= k)
  13.       break;
  14.     nCount += f[i];
  15.   }
  16.   k -= nCount;//计算k在i位数中的位置
  17.   int n = g[i] + k / i - 1, m = k % i;//计算出具体的数
  18.   //输出具体的数字
  19.   char str[12];
  20.   int nL;
  21.   if (m == 0)
  22.   {
  23.     _itoa_s(n, str, 10);
  24.     nL = strlen(str);
  25.   }
  26.   else
  27.   {
  28.     _itoa_s(n + 1, str, 10);
  29.     nL = m;
  30.   }
  31.   return int(str[nL - 1] - 48);
  32. }

  33. int main(void)
  34. {
  35.   int p = getDigit(1);
  36.   p *= getDigit(10);
  37.   p *= getDigit(100);
  38.   p *= getDigit(1000);
  39.   p *= getDigit(10000);
  40.   p *= getDigit(100000);
  41.   p *= getDigit(1000000);
  42.   cout << p << endl;
  43.   return 0;
  44. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-24 18:56:23 | 显示全部楼层
  1. import time as t

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

  6. product = 1
  7. for j in range(7):
  8.     print('d_%d = %s' % (10 ** j, d_n[10 ** j]))
  9.     product *= int(d_n[10 ** j])

  10. print(product)
  11. 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 | 显示全部楼层
  1. $ time ./main
  2. 210

  3. real        0m0.001s
  4. user        0m0.000s
  5. sys        0m0.001s
复制代码
  1. // count bits before 10^l
  2. fn cb(l: u32) -> u32 {
  3.     if l == 0 {
  4.         return 0;
  5.     }
  6.     9 * 10u32.pow(l - 1) * l + cb(l - 1)
  7. }

  8. // 返回第i位所在的数字以及偏移量
  9. fn b2n(x: u32) -> (u32, u32) {
  10.     let mut base_l = 1;
  11.     while cb(base_l) < x {
  12.         base_l += 1;
  13.     }
  14.     base_l -= 1;
  15.     (
  16.         (x - cb(base_l)) / (base_l + 1) + 10u32.pow(base_l) - 1,
  17.         (x - cb(base_l)) % (base_l + 1),
  18.     )
  19. }

  20. fn d(x: u32) -> u32 {
  21.     let (b, mut i) = b2n(x);
  22.     if i == 0 {
  23.         return b % 10;
  24.     }
  25.     let mut y = b + 1;
  26.     i = y.ilog10() + 2 - i;
  27.     let mut r = 0;
  28.     while i > 0 {
  29.         r = y % 10;
  30.         y /= 10;
  31.         i -= 1;
  32.     }
  33.     r
  34. }
  35. fn main() {
  36.     println!("{}", (0..=6).map(|x| d(10u32.pow(x))).product::<u32>())
  37. }
复制代码

测试
  1. #[cfg(test)]
  2. mod tests {
  3.     use super::*;
  4.     #[test]
  5.     fn test_cb() {
  6.         assert_eq!(cb(1), 9);
  7.         assert_eq!(cb(2), 189);
  8.     }
  9.     #[test]
  10.     fn test_b2n() {
  11.         assert_eq!(b2n(8), (8, 0));
  12.         assert_eq!(b2n(9), (9, 0));
  13.         assert_eq!(b2n(100), (54, 1));
  14.         assert_eq!(b2n(189), (99, 0));
  15.         assert_eq!(b2n(191), (99, 2));
  16.         assert_eq!(b2n(192), (100, 0));
  17.     }
  18.     #[test]
  19.     fn test_d() {
  20.         assert_eq!(d(1), 1);
  21.         assert_eq!(d(12), 1);
  22.         assert_eq!(d(13), 1);
  23.         assert_eq!(d(100), 5);
  24.     }
  25. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-29 02:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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