2018.10.05【NOIP提高组】模拟B组

\(5166.\) 卢学魔 \((Standard\ IO)\)

Time Limits: 1000 ms  
Memory Limits: 262144 KB  


考试的想法,一直 \(Dfs\) 到底部,然后方案数加一。

得分: \(20\)

原因: 补充一些生物知识:

  • 生产者不止一个

  • 一个生产者不是食物链

提示

  • \(Dfs\) 会爆栈,所以我写的是记忆化。记录它的叶子节点有多少个。保证每一个点只有出现一次。
var
	next,reach:array[-1..210007] of longint;
	cnt,dsu,size:array[-1..2100007] of longint;
	ans,l,r,i,j,n,m,tot:longint;

procedure Add(l,r:longint);
begin
        inc(tot);
        reach[tot]:=r;
        next[tot]:=cnt[l];
        cnt[l]:=tot;
end;

function Dfs(x:longint):longint;
var i,tmp:longint;
begin
	Dfs:=0; i:=cnt[x];
	if size[x]>0 then exit(size[x]);
	if (i=-1)and(dsu[x]<>0) then begin exit(1); end;
	while i<>-1 do
	begin
		tmp:=Dfs(reach[i]); inc(size[x],tmp); inc(Dfs,tmp);
		i:=next[i];
	end;
end;

begin
        filldword(cnt,sizeof(cnt) div 4,maxlongint*2+1);
	read(n,m);
	for i:=1 to m do begin read(l,r); Add(l,r); inc(dsu[r]); end;
	ans:=0;
	for i:=1 to n do if dsu[i]=0 then inc(ans,Dfs(i));
	writeln(ans);
end.

\(5167.\) 下蛋爷 \((Standard\ IO)\)

Time Limits: 1000 ms  
Memory Limits: 262144 KB

这个名字很棒。

首先我们先求出 \(stu_i\) 代表第 \(i\) 个 单词(\(word_i\)) 在字符串 (\(S\)) 中出现的次数。由于本人不会自动机,所以用 \(KMP\) 就可以了。

然后我们把 \(stu\) 数组离散化,从大到小排序。然后进行概率 \(DP\)。公式是 \(f[i,j]:=f[i-1,j]*p+f[i-1,j+1]*(1-p);\)。这个很好理解。

由于是 \(KMP\),所以只有 \(90\) 分,最后一个点可以打表。程序全场最慢,没有之一。

var
	S:ansistring;
	word:array[-1..2100] of string;
	stu,place:array[-1..2100] of longint;
	f:array[-1..2100,-1..2100] of real;
	ans,witn:array[-1..2100] of real;
	i,j,n,m,k,maxn:longint;
	p:real;

procedure Sort(l,r:longint);
var i,j,s,t:longint;
begin
	i:=l; j:=r; s:=stu[(l+r) div 2];
    repeat
        while stu[i]>s do inc(i);
        while stu[j]<s do dec(j);
        if i<=j then
        begin
            t:=stu[i]; stu[i]:=stu[j]; stu[j]:=t;
            t:=place[i]; place[i]:=place[j]; place[j]:=t;
		    inc(i); dec(j);
        end;
    until i>=j;
    if i<r then Sort(i,r);
    if j>l then Sort(l,j);
end;

function kmp(s,ss:ansistring):longint;
var
  	next:array[1..11000] of longint;
  	l1,l2,i,j:longint;
begin
  	kmp:=0; next[1]:=0;
  	j:=0; l1:=length(s); l2:=length(ss);
  	for i:=2 to l2 do
  	begin
    	while (j>0) and (ss[j+1]<>ss[i]) do j:=next[j];
    	if ss[j+1]=ss[i] then inc(j); next[i]:=j;
  	end;
  	j:=0;
  	for i:=1 to l1 do
  	begin
    	while (j>0) and (s[i]<>ss[j+1]) do j:=next[j];
    	if (j<l2) and (s[i]=ss[j+1]) then inc(j);
        if j=l2 then begin inc(kmp); j:=next[j]; end;
  	end;
end;

begin
	readln(n); for i:=1 to n do readln(word[i]); readln(S); readln(p,k);
	for i:=1 to n do begin stu[i]:=kmp(S,word[i]); place[i]:=i; end;
	Sort(1,n); 

	for i:=1 to n do if stu[i]<>stu[i-1] then inc(maxn);
	for i:=0 to maxn do f[0,i]:=1;
	for i:=1 to k do for j:=maxn downto 0 do f[i,j]:=f[i-1,j]*p+f[i-1,j+1]*(1-p);
	{for i:=1 to k do
	begin
        fillchar(ans,sizeof(ans),0);
		for j:=0 to maxn do ans[j]:=ans[j]+f[i,j];
		for j:=1 to n do witn[place[j]]:=ans[stu[j]];
		for j:=n downto 1 do write(witn[j]:0:3,' '); writeln;
	end; }
    maxn:=0;
    for i:=1 to n do
    begin
    	if stu[i]<>stu[i-1] then inc(maxn);
    	ans[place[i]]:=f[k,maxn];
    end;
    for i:=1 to n do write(ans[i]:0:3,' ');
end.

\(5168.\) 冲击哥 \((Standard\ IO)\)

Time Limits: 1000 ms  
Memory Limits: 262144 KB

一个一个扩展就好了,一个大贪心。还没有打出来,到时候再贴代码吧。

posted @ 2018-10-05 18:16  _ARFA  阅读(155)  评论(0编辑  收藏  举报