鱼C论坛

 找回密码
 立即注册
查看: 2825|回复: 2

题目154:研究帕斯卡金字塔

[复制链接]
发表于 2016-9-1 00:38:35 | 显示全部楼层 |阅读模式

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

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

x
Exploring Pascal's pyramid

A triangular pyramid is constructed using spherical balls so that each ball rests on exactly three balls of the next lower level.

p154_pyramid.gif


Then, we calculate the number of paths leading from the apex to each position:

A path starts at the apex and progresses downwards to any of the three spheres directly below the current position.

Consequently, the number of paths to reach a certain position is the sum of the numbers immediately above it (depending on the position, there are up to three numbers above it).

The result is Pascal's pyramid and the numbers at each level n are the coefficients of the trinomial expansion (x + y + z)n.

How many coefficients in the expansion of (x + y + z)200000 are multiples of 1012?


题目:

三角状的金字塔是用圆球建造的:每个球都与下一层的三个球相接触。

p154_pyramid.gif


于是,我们计算从顶点到任一点的路径数:

路径是从顶点开始,从下一层相接触的三个球中任选一个一直往下走。

那么,到达某一位置的路径的条数就是到达它上一层的路径数之和(取决于具体位置,一个球,最多可能有三条路径可以从上层到该位置,所以,最多只有三个路径数)。

这个结果就是帕斯卡金字塔,第n层的路径数是三项式乘方 (x + y + z)n的系数.

请问,(x + y + z)200000 的系数中,有多少个是 1012倍数?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-9-4 14:33:03 | 显示全部楼层
#(x + y + z)^n = ∑(n!/(r!* s!* t!) * x^r * y^s * z^t) ,r+s+t=n
所以问题变成 n!/(r!* s!* t!) 里有多少10^12的倍数,r+s+t=n
10^12分解成因子就是12个2和12个5
问题变成n!/r!s!t!有几个的2和5的因子数都大于等于12
算法很简单
只所以采用pascal实在是因为python计算太慢了(也可能我的算法不够优化)
delphi7运行的话大概1分半,python目测起码10个小时。。。
program p154;

{$APPTYPE CONSOLE}

uses
  SysUtils, Types, Windows,Math;
const
  maxn = 200000;
type
  nlist = array[0..maxn+5] of integer;
var
  st: DWord;
  twolist, fivelist: nlist;
  cnt: integer;
  r,s,t: integer;

  function getXcountin1n(const x: word): nlist;
  var
    cnt: integer;
    i,i1: integer;
  begin
    cnt := 0;
    for i:=0 to x-1 do
      result[i] := 0;
    i := x;
    while i <= maxn do
    begin
      i1 := i;
      while (i1 > 0) and (i1 mod x = 0) do
      begin
        inc(cnt);
        i1 := i1 div x
      end;
      for i1:= i to i+x-1 do
        result[i1] := cnt;
      inc(i, x);
    end;
  end;

begin
st := gettickcount();
twolist := getXcountin1n(2);
fivelist := getXcountin1n(5);
cnt := 0;
for r:= 0 to maxn do
begin
  for s:= 0 to (maxn-r) do
  begin
    t := maxn-r-s;
    if (twolist[maxn]-twolist[r]-twolist[s]-twolist[t] >= 12) and (fivelist[maxn]-fivelist[r]-fivelist[s]-fivelist[t] >= 12) then
       inc(cnt);
  end;
end;

writeln(cnt);  //479742450 87.4s
writeln(format('cost %n s', [(gettickcount-st)/1000]));
readln; //wait Enter
end.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-9-21 20:08:44 | 显示全部楼层
本帖最后由 guosl 于 2022-9-21 20:19 编辑

思路参考上面的帖子
/*
答案:479742450
耗时:1.24439秒(R5 5600G)
*/
#include <iostream>
#include <omp.h>
using namespace std;

const int N = 200000;
int p2[N + 1], p5[N + 1];

int main(void)
{
  long long nCount = 0;
  #pragma omp parallel shared (p2,p5) reduction(+:nCount)
  {
#pragma omp for
    for (int i = 2; i <= N; ++i)
    {
      int k = 2;
      while (k <= i)
      {
        p2[i] += i / k;
        k *= 2;
      }
      k = 5;
      while (k <= i)
      {
        p5[i] += i / k;
        k *= 5;
      }
    }
    for (int i = 0; i <= N; ++i)
    {
#pragma omp for
      for (int j = 0; j <= N - i; ++j)
      {
        int k = N - i - j;
        int c2 = p2[N] - p2[i] - p2[j] - p2[k];
        int c5 = p5[N] - p5[i] - p5[j] - p5[k];
        if (c2 >= 12 && c5 >= 12)
          ++nCount;
      }
    }
  }
  cout << nCount << endl;
  return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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