|
发表于 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;
- }
复制代码 |
|