Sgoi9-4解题报告
   
算法

  容易看出:客人到来的情况是无关紧要的,也就是说:有用的只是m,n,k这三个数。
  如果利用简单的动态规划,在时间上是无法承受的。但是却可以得到一些m、n、k不太大时的结果,帮助我们找到规律。
  经过观察,发现:本题的答案就是
  现在关键在于计算,约分后写成……的形式(为质数)。为了加快速度,采用二分法求乘幂、一位保存多位优化高精度,就可以在时限内出来了。

参考程序

{$r-,s-,q-}

const
 finp = 'dance.in';
 fout = 'dance.out';
 maxn = 10000;

 digits = 8;
 maxvalue = 100000000.0; {pow(10, digits)}
 maxll = 10000;
 maxkk = maxll div digits + 1;

type
 TBigNumber = record
  l: integer;
  num: array[1 .. maxkk] of comp;
 end;

var
 x: array[1 .. maxn] of byte;
 w: array[1 .. maxn] of integer;
 i, j, k, l, n, m, q, maxlen, maxk: integer;
 r, pp: TBigNumber;
 rr: array[1 .. maxkk] of comp;
 v, p: comp;
 s: string;
begin
 assign(input, finp);
 reset(input);
 readln(n, m, maxlen);
 close(input);
 maxk := maxlen div digits + 1;
 fillchar(x, sizeof(x), 0);
 for i := 2 to trunc(sqrt(n)) + 1 do
 if x[i] = 0 then
 begin
  k := i * i;
  while k <= maxn do
  begin
   x[k] := i;
   k := k + i;
  end;
 end;
fillchar(w, sizeof(w), 0);
for i := n - m + 1 to n do
 w[i] := w[i] + 2;
for i := 1 to m do
 w[i] := w[i] - 1;
for i := n downto 1 do
 if x[i] <> 0 then
 begin
  w[x[i]] := w[x[i]] + w[i];
  w[i div x[i]] := w[i div x[i]] + w[i];
  w[i] := 0;
 end;
if w[2] < w[5] then
 i := w[2]
else
 i := w[5];
w[2] := w[2] - i;
w[5] := w[5] - i;
r.l := 1;
r.num[r.l] := 1;
for m := n downto 2 do
 if w[m] <> 0 then
 begin
  pp.l := 1;
  pp.num[pp.l] := m;
  q := w[m];
  while q and (q - 1) <> 0 do
   q := q and (q - 1);
  k := 1;
  while q > 1 do
  begin
   fillchar(rr, sizeof(rr), 0);
   l := pp.l;
   i := 1;
   while i <= l do
   begin
    p := pp.num[i];
    k := i shl 1 - 1;
    rr[k] := rr[k] + p * p;
    p := p + p;
    i := i + 1;
    for j := i to l do
    begin
     k := k + 1;
     rr[k] := rr[k] + p * pp.num[j];
    end;
    if k = maxk then
     l := l - 1;
   end;
   l := l + pp.l;
   if l > maxk then
    l := maxk;
   p := 0;
   for i := 1 to l do
   begin
    v := rr[i] + p;
    p := int(v / maxvalue);
    pp.num[i] := v- p * maxvalue;
   end;
   if pp.num[l] = 0 then
    l := l - 1;
   q := q shr 1;
   if w[m] and q <> 0 then
   begin
    p := 0;
    for i := 1 to l do
    begin
     v := pp.num[i] * m + p;
     p := int(v / maxvalue);
     pp.num[i] := v - p * maxvalue;
    end;
    if (l < maxk) and (p <> 0) then
    begin
     l := l + 1;
     pp.num[l] := p;
    end;
   end;
   pp.l := l;
  end;
  l := r.l;
  fillchar(rr, sizeof(rr), 0);
  for i := 1 to pp.l do
  begin
   p := pp.num[i];
   k := i;
   for j := 1 to l do
   begin
    rr[k] := rr[k] + p * r.num[j];
    k := k + 1;
   end;
   if k = maxk + 1 then
    l := l - 1;
  end;
  l := l + pp.l;
  p := 0;
 for i := 1 to l do
 begin
  v := p + rr[i];
  p := int(v / maxvalue);
  r.num[i] := v - p * maxvalue;
 end;
 if r.num[l] = 0 then
  r.l := l - 1
 else
  r.l := l;
 end;
fillchar(x, sizeof(x), 0);
str(r.num[r.l] : 0 : 0, s);
l := length(s);
for i := 1 to l do
 x[i] := byte(s[i]);
for i := r.l - 1 downto 1 do
begin
 str(r.num[i] : 0 : 0, s);
 while length(s) < digits do
  s := '0' + s;
 for k := 1 to length(s) do
  x[(r.l - i - 1) * digits + l + k] := byte(s[k]);
 end;
 l := (r.l - 1) * digits + l;
 k := 1;
 while (l - k + 1 > maxlen) or (x[k] = ord('0')) do
  k := k + 1;
 assign(output, fout);
 rewrite(output);
 for i := k to l do
  write(char(x[i]));
 close(output);
end.

   

 
网站导航 | 关于曙光 | 联系我们 | 请提意见
Copyright © FuJian Sunshine Educational Info. Co.,Ltd.
福建曙光教育资讯有限公司 版权所有