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)∗t11∗s
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.