17.9.23B组总结

17.9.23B组总结

T1

赤裸裸的一道水题(我并非大佬),用暴力就好了。

T2

考试懵逼,看完正解后恍然大悟,不要被他表面现象所迷惑,第一问就是一个最长不下降子序列。至于第二问嘛,不过反过来做一遍最长不上升子序列,取交集即可。
来一波代码

uses math;
var
        n,i,j,ans,w,tot,t,s:longint;
        a,f,ff,b,bz:array[0..100000]of longint;
function er(x:longint):longint;
var
        l,r,mid:longint;
begin
        l:=1;
        r:=j;
        er:=0;
        while l<=r do
        begin
                mid:=(l+r) div 2;
                if b[mid]<x then
                begin
                        er:=mid;
                        l:=mid+1;
                end
                else
                        r:=mid-1;
        end;
        inc(er);
end;
function ere(x:longint):longint;
var
        l,r,mid:longint;
begin
        l:=1;
        r:=j;
        ere:=0;
        while l<=r do
        begin
                mid:=(l+r) div 2;
                if b[mid]>x then
                begin
                        ere:=mid;
                        l:=mid+1;
                end
                else
                        r:=mid-1;
        end;
        inc(ere);
end;
begin
        readln(n);
        for i:=1 to n do
                read(a[i]);
        readln;
        j:=0;
        for i:=1 to n do
        begin
                if a[i]>=b[j] then
                begin
                        inc(j);
                        b[j]:=a[i];
                        f[i]:=j;
                end
                else
                begin
                        f[i]:=er(a[i]);
                        b[f[i]]:=a[i];
                end;
        end;
        s:=j;
        writeln(s);
        j:=0;
        fillchar(b,sizeof(b),0);
        b[0]:=maxlongint;
        for i:=n downto 1 do
        begin
                if a[i]<=b[j] then
                begin
                        inc(j);
                        b[j]:=a[i];
                        ff[i]:=j;
                end
                else
                begin
                        ff[i]:=ere(a[i]);
                        b[ff[i]]:=a[i];
                end;
        end;
        for i:=1 to n do
                if f[i]+ff[i]-1=s then
                        inc(bz[f[i]]);
        for i:=1 to n do
                if (f[i]+ff[i]-1=s)and(bz[f[i]]=1) then
                        write(i,' ');
        writeln;
end.

T3

真的改得我好辛苦好累呀,试了三种方法,终于切了此题。
网上题解(刘犇真情推荐):http://blog.csdn.net/lyd_7_29/article/details/54619437(帮别人刷访问量~)。
大致是这样的:
设f[i][j][0/1]表示当前树大小为i,任意编号都可能当根,形成最大匹配数为j,0 or 1表示匹配中有无根
一个子树时显然:

f[i+1][x][0]+=(i+1)f[i][x][1]

f[i+1][x+1][1]+=(i+1)f[i][x][0]

两边都有子树时要枚举另外一边,处理出:
s=Cii+j

当i=j时s=s/2;
t00=f[i][x][0]f[j][y][0]
t01=f[i][x][0]f[j][y][1]
t10=f[i][x][1]f[j][y][0]
t11=f[i][x][1]f[j][y][1]
接着最重要的更新答案:
f[i+j+1][x+y][0]+=(i+j+1)t11s

f[i+j+1][x+y+1][1]+=(i+j+1)(t00+t01+t10)s

记得所有除要改用逆元。
标(不要co,有害身心)

uses math;
const
        mo=1000000007;
var
        n,k,i,j,x,y:longint;
        s,t00,t01,t10,t11,b:int64;
        f:array[0..50,0..50,0..1]of int64;
        c:array[0..100]of int64;
function ff(x,y:int64):int64;
var
        s:int64;
begin
        s:=1;
        while y>0 do
        begin
                if y and 1=1 then
                        s:=s*x mod mo;
                x:=x mod mo*x mod mo;
                y:=y div 2;
        end;
        exit(s);
end;
begin
        readln(n,k);
        c[0]:=1;
        for i:=1 to n do
                c[i]:=c[i-1]*i mod mo;
        f[0,0,0]:=1;
        f[1,0,0]:=1;
        b:=ff(c[2],mo-2);
        for i:=1 to n-1 do
        begin
                for j:=0 to min(k,i div 2) do
                begin
                        f[i+1,j,0]:=(f[i+1,j,0]+(i+1)*f[i,j,1] mod mo) mod mo;
                        f[i+1,j+1,1]:=(f[i+1,j+1,1]+(i+1)*f[i,j,0] mod mo) mod mo;
                        for x:=1 to min(i,n-i-1) do
                        begin
                                for y:=0 to x div 2 do
                                begin
                                        s:=c[i+x]*ff(c[i],mo-2) mod mo*ff(c[x],mo-2) mod mo;
                                        if i=x then
                                                s:=s*b mod mo;
                                        t00:=f[i,j,0]*f[x,y,0] mod mo;
                                        t01:=f[i,j,0]*f[x,y,1] mod mo;
                                        t10:=f[i,j,1]*f[x,y,0] mod mo;
                                        t11:=f[i,j,1]*f[x,y,1] mod mo;
                                        f[i+x+1,j+y,0]:=(f[i+x+1,j+y,0]+(i+x+1)*t11 mod mo*s mod mo) mod mo;
                                        f[i+x+1,j+y+1,1]:=(f[i+x+1,j+y+1,1]+(i+x+1)*(t00+t01+t10) mod mo*s mod mo) mod mo;
                                end;
                        end;
                end;
        end;
        writeln((f[n,k,1]+f[n,k,0]) mod mo*ff(n,mo-2) mod mo);
end.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值