鱼C论坛

 找回密码
 立即注册
查看: 2774|回复: 4

题目113:一个googol(10^100)以下有多少数字不是跳跃数?

[复制链接]
发表于 2016-8-21 01:04:18 | 显示全部楼层 |阅读模式

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

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

x
Non-bouncy numbers

Working from left-to-right if no digit is exceeded by the digit to its left it is called an increasing number; for example, 134468.

Similarly if no digit is exceeded by the digit to its right it is called a decreasing number; for example, 66420.

We shall call a positive integer that is neither increasing nor decreasing a "bouncy" number; for example, 155349.

As n increases, the proportion of bouncy numbers below n increases such that there are only 12951 numbers below one-million that are not bouncy and only 277032 non-bouncy numbers below QQ20160821-2@2x.png .

How many numbers below a googol QQ20160821-3@2x.png are not bouncy?


题目:

如果一个数的每一位都大于等于前一位,则称其为递增数,例如 134468。

类似的,如果一个数的每一位都小于等于前一位,则称其为递减数,例如 66420。

如果一个正整数既不是递增数也不是递减数,则称其为一个“跳跃数”,例如 155349。

随着 n 的增加,小于 n 的跳跃数的比例不断增加,以至于到了一百万以下的数中只有 12951 个不是跳跃数, QQ20160821-2@2x.png 以下只有 277032 个数不是跳跃数。

一个googol QQ20160821-3@2x.png 以下的数中有多少个不是跳跃数?

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-8-31 17:34:49 | 显示全部楼层
googol是啥意思
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-6 21:28:03 | 显示全部楼层
  1. from math import factorial as f
  2. print(sum([f(i+8)//f(i)//f(8) for i in range(1, 101)]) + sum([f(i+9)//f(i)//f(9) for i in range(1, 101)]) - 10*100)
复制代码

51161058134250
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-8 09:52:58 | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2021-7-8 19:13 编辑

C++ 2ms
  1. #include<iostream>
  2. using ulong = unsigned long long;


  3. template<size_t size>
  4. constexpr ulong sum(ulong(&array)[size])noexcept {
  5.     ulong result = 0;

  6.     for (ulong i : array) {
  7.         result += i;
  8.     }

  9.     return result;
  10. }


  11. template<size_t size>
  12. constexpr void accumulate(ulong(&array)[size]) noexcept { //累加函数,参考 Python 的 itertools.accumulate
  13.     for (size_t index = 1; index < size; index++) {
  14.         array[index] += array[index - 1];
  15.     }
  16. }


  17. constexpr ulong non_bouncy(size_t digits)noexcept {
  18.     switch (digits) {
  19.     case 0:
  20.     case 1:
  21.         return 0;
  22.     }

  23.     ulong array[]{ 1,2,3,4,5,6,7,8,9,9 };
  24.     ulong result =
  25.         9 //1位数既不是递增数也不是递减数
  26.         + sum(array) * 2 - array[9] //递增数和递减数的和
  27.         - --digits * 9 //每位都相同的数字,既属于递增数又属于递减数
  28.         ;

  29.     while (--digits) {
  30.         accumulate(array);
  31.         result += sum(array) * 2 - array[9];//递增数和递减数的和
  32.     }

  33.     return result;
  34. }


  35. int main() {
  36.     using namespace std;
  37.     ios::sync_with_stdio(false);
  38.     cout << non_bouncy(100) << endl;
  39.     return 0;
  40. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-10 11:45:20 | 显示全部楼层
本帖最后由 guosl 于 2022-2-10 11:48 编辑

本题所涉及的数比较大故在程序中用了大数库mpir。
  1. /*
  2. 答案:51161058134250
  3. 耗时:0.000191秒
  4. */
  5. #include <iostream>
  6. #include <mpir.h>
  7. #include <omp.h>
  8. using namespace std;

  9. int f[10][10];//f[i][j]为长度是i且最后一个数的值是j的严格递增序列的个数
  10. int g[11][10];//g[i][j]为长度是i且最后一个数的值是j的严格递减序列的个数

  11. int main(void)
  12. {
  13.   double d = omp_get_wtime();
  14.   for (int i = 1; i < 10; ++i)
  15.   {
  16.     f[1][i] = 1;//长度为1的序列只有一个
  17.     g[1][i] = 1;//长度为1的序列只有一个
  18.   }
  19.   for (int i = 2; i < 10; ++i)
  20.   {
  21.     for (int j = 1; j < 10; ++j)
  22.     {
  23.       for (int k = 1; k < j; ++k)
  24.         f[i][j] += f[i - 1][j - k];
  25.     }
  26.   }
  27.   for (int i = 2; i <= 10; ++i)
  28.   {
  29.     for (int j = 1; j < 10; ++j)
  30.     {
  31.       for (int k = 1; k <= j; ++k)
  32.         g[i][j - k] += g[i - 1][j];
  33.     }
  34.   }
  35.   mpz_t zSum, t;
  36.   mpz_inits(zSum, t, 0);
  37.   mpz_set_ui(zSum, 99);
  38.   for (int w = 3; w <= 100; ++w)//对数字位数进行枚举
  39.   {
  40.     //计算递增数的个数
  41.     for (int k = 1; k < 9; ++k)//枚举跳跃点的个数
  42.     {
  43.       if (k > w - 1)
  44.         break;
  45.       mpz_bin_uiui(t, w - 1, k);//跳跃点的选取方式数
  46.       int s = 0;
  47.       //此时跳跃数组的长度为k+1
  48.       for (int a = 1; a < 10; ++a)//计算具体的递增数组的选取方式数
  49.         s += f[k + 1][a];
  50.       mpz_mul_si(t, t, s);
  51.       mpz_add(zSum, zSum, t);
  52.     }
  53.     //计算递减数的个数
  54.     for (int k = 1; k <= 9; ++k)//枚举跳跃点的个数
  55.     {
  56.       if (k > w - 1)
  57.         break;
  58.       mpz_bin_uiui(t, w - 1, k);//跳跃点的选取方式数
  59.       int s = 0;
  60.       //此时跳跃数组的长度为k+1
  61.       for (int a = 0; a < 10; ++a)//计算具体的递减数组的选取方式数
  62.         s += g[k + 1][a];
  63.       mpz_mul_si(t, t, s);
  64.       mpz_add(zSum, zSum, t);
  65.     }
  66.     mpz_add_ui(zSum, zSum, 9);//加上跳跃数为0的数的个数
  67.   }
  68.   d = omp_get_wtime() - d;
  69.   gmp_printf("%Zd\n%lf\n", zSum, d);
  70.   mpz_clears(zSum, t, 0);
  71.   return 0;
  72. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-23 21:15

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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