鱼C论坛

 找回密码
 立即注册
查看: 2442|回复: 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 以下的数中有多少个不是跳跃数?

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

使用道具 举报

发表于 2016-8-31 17:34:49 | 显示全部楼层
googol是啥意思
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-6 21:28:03 | 显示全部楼层
from math import factorial as f
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
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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


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

    for (ulong i : array) {
        result += i;
    }

    return result;
}


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


constexpr ulong non_bouncy(size_t digits)noexcept {
    switch (digits) {
    case 0:
    case 1:
        return 0;
    }

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

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

    return result;
}


int main() {
    using namespace std;
    ios::sync_with_stdio(false);
    cout << non_bouncy(100) << endl;
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

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

int main(void)
{
  double d = omp_get_wtime();
  for (int i = 1; i < 10; ++i)
  {
    f[1][i] = 1;//长度为1的序列只有一个
    g[1][i] = 1;//长度为1的序列只有一个
  }
  for (int i = 2; i < 10; ++i)
  {
    for (int j = 1; j < 10; ++j)
    {
      for (int k = 1; k < j; ++k)
        f[i][j] += f[i - 1][j - k];
    }
  }
  for (int i = 2; i <= 10; ++i)
  {
    for (int j = 1; j < 10; ++j)
    {
      for (int k = 1; k <= j; ++k)
        g[i][j - k] += g[i - 1][j];
    }
  }
  mpz_t zSum, t;
  mpz_inits(zSum, t, 0);
  mpz_set_ui(zSum, 99);
  for (int w = 3; w <= 100; ++w)//对数字位数进行枚举
  {
    //计算递增数的个数
    for (int k = 1; k < 9; ++k)//枚举跳跃点的个数
    {
      if (k > w - 1)
        break;
      mpz_bin_uiui(t, w - 1, k);//跳跃点的选取方式数
      int s = 0;
      //此时跳跃数组的长度为k+1
      for (int a = 1; a < 10; ++a)//计算具体的递增数组的选取方式数
        s += f[k + 1][a];
      mpz_mul_si(t, t, s);
      mpz_add(zSum, zSum, t);
    }
    //计算递减数的个数
    for (int k = 1; k <= 9; ++k)//枚举跳跃点的个数
    {
      if (k > w - 1)
        break;
      mpz_bin_uiui(t, w - 1, k);//跳跃点的选取方式数
      int s = 0;
      //此时跳跃数组的长度为k+1
      for (int a = 0; a < 10; ++a)//计算具体的递减数组的选取方式数
        s += g[k + 1][a];
      mpz_mul_si(t, t, s);
      mpz_add(zSum, zSum, t);
    }
    mpz_add_ui(zSum, zSum, 9);//加上跳跃数为0的数的个数
  }
  d = omp_get_wtime() - d;
  gmp_printf("%Zd\n%lf\n", zSum, d);
  mpz_clears(zSum, t, 0);
  return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-22 21:02

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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