bzoj 1089 SCOI2003严格n元树 递推

挺好想的,就是一直没调过,我也不知道哪儿的错,对拍也拍了,因为数据范围小,都快手动对拍了也不知道

哪儿错了。。。。

我们定义w[i]代表深度<=i的严格n元树的个数

那么最后w[d]-w[d-1]就是答案

那么对于w[i],我们由w[i-1]递推来,

我们考虑新加一个根节点,然后根节点有n个子节点,每个子节点都可以建一颗深度<=i-1的树,那么每个

子节点都有w[i-1]种选法,那么n个子节点就有w[i-1]^n选法,再加上都不选,就是深度为0的情况

那么w[i]:=(w[i-1]^n)+1;

//By BLADEVIL
var
    w                           :array[-1..100] of ansistring;
    n, d                        :longint;
    a, b, c                     :array[0..100000] of int64;
 
function mul(s1,s2:ansistring):ansistring;
var
    i, j                        :longint;
    len1, len2                  :longint;
    s                           :ansistring;
begin
    len1:=length(s1);
    len2:=length(s2);
    fillchar(c,sizeof(c),0);
    fillchar(a,sizeof(a),0);
    fillchar(b,sizeof(b),0);
    for i:=1 to len1 do a[(len1-i) div 4+1]:=a[(len1-i) div 4+1]*10+ord(s1[i])-48;
    for i:=1 to len2 do b[(len2-i) div 4+1]:=b[(len2-i) div 4+1]*10+ord(s2[i])-48;
    len1:=(len1+3) div 4;
    len2:=(len2+3) div 4;
    for i:=1 to len1 do
        for j:=1 to len2 do
        begin
            c[i+j-1]:=c[i+j-1]+a[i]*b[j];
            c[i+j]:=c[i+j]+c[i+j-1] div 10000;
            c[i+j-1]:=c[i+j-1] mod 10000;
        end;
    mul:='';
    len1:=len1+len2+1;
    for i:=len1 downto 1 do
    begin
        if c[i]<1000 then mul:=mul+'0';
        if c[i]<100 then mul:=mul+'0';
        if c[i]<10 then mul:=mul+'0';
        str(c[i],s);
        mul:=mul+s;
    end;
    while (mul[1]='0') and (length(mul)>1) do delete(mul,1,1);
end;
 
function mi(x:ansistring):ansistring;
var
    p                           :longint;
    ans, sum                    :ansistring;
begin
    ans:='1';
    sum:=x;
    p:=n;
    while p<>0 do
    begin
        if p mod 2=1 then ans:=mul(ans,sum);
        p:=p div 2;
        sum:=mul(sum,sum);
    end;
    mi:=ans;
end;
     
function inc(x:ansistring):ansistring;
var
    len                         :longint;
    i                           :longint;
    s                           :ansistring;
     
begin
    len:=length(x);
    for i:=1 to len do c[i]:=ord(x[i])-48;
    c[len]:=c[len]+1;
    for i:=len downto 1 do
    begin
        c[i-1]:=c[i-1]+c[i] div 10;
        c[i]:=c[i] mod 10;
    end;
    inc:='';
    len:=len;
    for i:=0 to len do
    begin
        str(c[i],s);
        inc:=inc+s;
    end;
    while (inc[1]='0') and (length(inc)>1) do delete(inc,1,1);
end;
     
function jian(s1,s2:ansistring):ansistring;
var
    i                           :longint;
    len1, len2                  :longint;
    s                           :ansistring;
begin
    len1:=length(s1);
    len2:=length(s2);
    fillchar(c,sizeof(c),0);
    for i:=1 to len1 do a[len1-i+1]:=ord(s1[i])-48;
    for i:=1 to len2 do b[len2-i+1]:=ord(s2[i])-48;
    for i:=1 to len1 do c[i]:=a[i]-b[i];
    for i:=1 to len1 do
        if c[i]<0 then
        begin
            c[i]:=c[i]+10;
            c[i+1]:=c[i+1]-1;
        end;
    jian:='';
    for i:=len1 downto 1 do
    begin
        str(c[i],s);
        jian:=jian+s;
    end;
    while (jian[1]='0') and (length(jian)>1) do delete(jian,1,1);
end;
     
procedure main;
var
    i                           :longint;
begin
    readln(n,d);
    if d=0 then 
    begin
        writeln(1);
        exit;
    end;
    w[0]:='1';
    for i:=1 to d do w[i]:=inc(mi(w[i-1]));
    writeln(jian(w[d],w[d-1]));
end;
    
begin
    main;
end.

 

posted on 2013-12-09 13:42  BLADEVIL  阅读(788)  评论(0编辑  收藏  举报