鱼C论坛

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

题目78:考察硬币划分的方式数量

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

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

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

x
Coin partitions

Let p(n) represent the number of different ways in which n coins can be separated into piles. For example, five coins can be separated into piles in exactly seven different ways, so p(5)=7.

OOOOO

OOOO   O

OOO   OO

OOO   O   O

OO   OO   O

OO   O   O   O

O   O   O   O   O

Find the least value of n for which p(n) is divisible by one million.

题目:

用 p(n) 表示 n 个硬币可以被划分成堆的方式。例如,5 个硬币可以被用 7 种方式划分成堆,所以 p(5)=7。

OOOOO

OOOO   O

OOO   OO

OOO   O   O

OO   OO   O

OO   O   O   O

O   O   O   O   O

找到 p(n) 可以被一百万整除的最小的 n 。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-12-31 20:37:01 | 显示全部楼层
这题是参考了维基百科上的计算公式:
According Wikipedia's information:
p(k) = p(k-(3*n*n-n)/2) + p(k-(3*n*n+n)/2) - p(k-(3*n*n+5*n+2)/2) - p(k-(3*n*n+7*n+4)/2) +... (n from 1 to ...) while p(0) = 1 and p(1) = 1
有了迭代公式,写程序相对还是比较容易的:
  1. pdic = {0:1,1:1}
  2. def p(k):
  3.         global pdic
  4.         s = 0
  5.         if k == 0 or k == 1:
  6.                 return 1
  7.         for n in range(1,int(k**0.5+1),2):
  8.                 a = k-(3*n*n-n)/2
  9.                 b = k-(3*n*n+n)/2
  10.                 c = k-(3*n*n+5*n+2)/2
  11.                 d = k-(3*n*n+7*n+4)/2
  12.                 if a >= 0:
  13.                         s += pdic[a]
  14.                 else:
  15.                         break
  16.                 if b >= 0:
  17.                         s += pdic[b]
  18.                 else:
  19.                         break
  20.                 if c >= 0:
  21.                         s -= pdic[c]
  22.                 else:
  23.                         break
  24.                 if d >= 0:
  25.                         s -= pdic[d]
  26.                 else:
  27.                         break
  28.         pdic[k] = s
  29.         return s

  30. for i in range(100000):
  31.         if p(i) % 1000000 == 0:
  32.                 print (i)
  33.                 break
复制代码

大约8秒钟可以出结果:
55374
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-4-26 10:54:52 | 显示全部楼层
本帖最后由 guosl 于 2021-3-21 12:56 编辑

这题也可以通过组合数学中的母函数展开来做。只是时间比较长。但可以用GPU来编程计算。在GTX1060上2秒多点可以得出结果。
  1. /*
  2. 用母函数展开来做
  3. 答案:55374
  4. 耗时:2.07287秒(GTX1060显卡)
  5. */
  6. #include <iostream>
  7. #include <algorithm>
  8. #include <cuda_runtime.h>
  9. #include <device_launch_parameters.h>
  10. #include <helper_cuda.h>
  11. using namespace std;

  12. const int N = 64000;
  13. const int nBlocksSize = 256;

  14. int *a, *b, c[N];
  15. bool *bFind;

  16. __global__ void Polynomial_Mul(int *p1, int *p2, int k, bool *bFlag)
  17. {
  18.   int i = blockIdx.x * nBlocksSize + threadIdx.x;
  19.   if (i >= N)
  20.     return;
  21.   p2[i] = 0;
  22.   for (int j = 0; j <= i; j += k)
  23.   {
  24.     p2[i] += p1[i - j];
  25.     p2[i] %= 1000000;
  26.   }
  27.   if (i == k)
  28.   {
  29.     if (p2[k] == 0)
  30.       *bFlag = true;
  31.   }
  32. }

  33. void find_zero(int *p1, int *p2, int k)
  34. {
  35.   Polynomial_Mul <<<N / nBlocksSize, nBlocksSize >>> (p1, p2, k, bFind);
  36. }

  37. int main(void)
  38. {
  39.   cudaDeviceProp deviceProp;
  40.   int devID = gpuGetMaxGflopsDeviceId();
  41.   cudaSetDevice(devID);//设置计算卡
  42.   cudaGetDeviceProperties(&deviceProp, devID);
  43.   printf("GPU Device %d: "%s" with compute capability %d.%d\n\n",
  44.     devID, deviceProp.name, deviceProp.major, deviceProp.minor);
  45.   //在显卡上分配内存
  46.   cudaMalloc((void**)&a, N * sizeof(int));
  47.   cudaMalloc((void**)&b, N * sizeof(int));
  48.   cudaMalloc((void**)&bFind, sizeof(int));
  49.   //设置计算的初始向量
  50.   for (int i = 0; i < N; ++i)
  51.     c[i] = 1;
  52.   cudaMemcpy(a, c, N * sizeof(int), cudaMemcpyHostToDevice);
  53.   int *p1 = a, *p2 = b;
  54.   for (int k = 2; k < N; ++k) //开始逐个展开母函数
  55.   {
  56.     bool bFlag = false;//设置返回值的初值
  57.     cudaMemcpy(bFind, &bFlag, sizeof(bool), cudaMemcpyHostToDevice);
  58.     find_zero(p1, p2, k);//计算第k次展开
  59.     swap(p1, p2);
  60.     cudaGetLastError();
  61.     cudaDeviceSynchronize();//等待计算完成
  62.     cudaMemcpy(&bFlag, bFind, sizeof(bool), cudaMemcpyDeviceToHost);//获取本次计算的结果
  63.     if (bFlag)//找到结果
  64.     {
  65.       cout << k << endl;
  66.       break;
  67.     }
  68.   }
  69.   cudaFree(a);
  70.   cudaFree(b);
  71.   cudaFree(bFind);
  72.   return 0;
  73. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-4 14:52:29 | 显示全部楼层
  1. from numba import jit

  2. @jit
  3. def solve():
  4.   mod = 10 ** 6
  5.   bound = 10 ** 5
  6.   dp = [0] * bound
  7.   dp[0] = 1
  8.   for i in range(1, bound):
  9.     for j in range(i, bound):
  10.       dp[j] = (dp[j] + dp[j-i]) % mod
  11.     if dp[i] == 0:
  12.       print(i)
  13.       break

  14. solve()
复制代码


https://github.com/devinizz/project_euler/blob/master/page02/78.py
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-11 12:46:37 From FishC Mobile | 显示全部楼层
和76好像有点关系
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-11 15:17

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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