LKOJ20201126Contest

比赛入口

这场考试没有认真做,就最后二十分钟打了两个暴力,于是\(20pts\)垫底了。

貌似跟高二的一起考垫底也不是什么很丢脸的事_

下午我们初三内部考试的时候,我花时间改了一下上午的题(然而由于题太简单还是有人\(AK\)了,\(orz:xzy,fkq\))。

觉得上午的题还是有很多可以值得学习的地方,努力做做\(200+\)应该是没问题的。

\(T1.\quad walking\)

有巨佬一看题就说是\(kmp\)\(SA\)\(SAM\)……(不像我一看题就没思路

这是\(T1\)啊,哪有那么复杂……

模式串长度不超过\(100\),轨迹串长度不超过\(1e6\),这明显的\(\Theta(nm)\)复杂度。

考虑开\(bool\)数组\(dp[i][j]\)表示模式串前\(i\)个和轨迹串前\(j\)个是否匹配。

转移显然。\(get:\)搜索状态多\(\rightarrow dp\)。注意细节。

考后改题代码:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f; 
}
const int maxn=1e6+10;
const int N=105;
int n,ls,lt;
bool dp[N][maxn];
char s[N],t[maxn];
int main(){
	freopen("walking.in","r",stdin);
	freopen("walking.out","w",stdout);
	scanf("%s",s+1);
	ls=strlen(s+1);
	n=read();
	for(int cs=1;cs<=n;cs++){
		scanf("%s",t+1);
		lt=strlen(t+1);
		for(int i=0;i<=ls;i++)
			for(int j=0;j<=lt;j++)
				dp[i][j]=false;
		dp[0][0]=true;
		for(int i=0;i<ls;i++){
			if(s[i+1]=='*'){
				for(int j=0;j<=lt;j++)
					if(dp[i][j]==true){
						for(int k=j;k<=lt;k++)
							dp[i+1][k]=true;
						break;
					}
			}else if(s[i+1]=='?'){
				for(int j=0;j<lt;j++)
					if(dp[i][j]==true)dp[i+1][j+1]=true;
			}else if(s[i+1]=='['){
				int cnt=1,pos=i+2;
				while(cnt&&pos<=ls){
					if(s[pos]=='[')cnt++;
					if(s[pos]==']')cnt--;
					pos++;
				}
				for(int j=0;j<=lt;j++)
					if(dp[i][j]==true){
						dp[pos-1][j]=true;
						dp[i+1][j]=true;
					}
			}else if(s[i+1]==']'){
				for(int j=0;j<=lt;j++)
					if(dp[i][j]==true)dp[i+1][j]=true;
			}else{
				for(int j=0;j<lt;j++)
					if(dp[i][j]==true&&s[i+1]==t[j+1])
						dp[i+1][j+1]=true;
			}
		}
		for(int i=1;i<=lt;i++)
			if(dp[ls][i]==true)printf("1");
			else printf("0");
		puts("");
	}
	return 0;
}

\(T2.\quad deconstruct\)

一道期望题,最令我头疼的期望题。

其实这道题菊花和链的部分分显然,这就有\(30pts\)了,但是后来没打。

\(note:\)由于期望与不相关的边的断边顺序无关,故只需考虑相关边即可。

菊花:答案为\(n-1\)

链:记\(f_i\)为长度为\(i\)的链的答案,\(f_0=0\),有转移\(f_i=\frac{1}{i}\sum\limits_{j=0}^{i-1}(f_j+f_{i-j-1}+i-j)\),答案为\(f_{n-1}\)

正解:考虑每一个节点\(x\)对其祖先\(y\)产生贡献的期望。

\(x\)\(y\)产生贡献当且仅当在\(x\rightarrow y\)的路径上与\(y\)相连的边第一个被断,其期望为\(\frac{1}{dis_{x\rightarrow y}}\)

将其求和即得总期望:\(E=\sum\limits_{i=1}^n\sum\limits_{j=1}^{dep_i}\frac{1}{j}\),预处理前缀和,遍历全树即可。

考后改题代码:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f; 
}
const int maxn=2e6+10;
const int mod=1e9+7;
int n,dep[maxn],inv[maxn],ans;
int beg[maxn],nex[maxn],to[maxn],e;
inline void add(int x,int y){
	e++;nex[e]=beg[x];
	beg[x]=e;to[e]=y;
}
inline void dfs(int x,int fa){
	dep[x]=dep[fa]+1;
	ans=(ans+inv[dep[x]-1])%mod;
	for(int i=beg[x];i;i=nex[i])
		dfs(to[i],x);
}
int main(){
	freopen("deconstruct.in","r",stdin);
	freopen("deconstruct.out","w",stdout);
	n=read();inv[1]=1;
	for(int i=2;i<=n;i++)
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for(int i=2;i<=n;i++)
		inv[i]=(inv[i]+inv[i-1])%mod;
	int x;
	for(int i=2;i<=n;i++){
		x=read();
		add(x,i);
	}
	dfs(1,1);
	printf("%d\n",ans);
	return 0;
}

\(T3.\quad stone\)(先咕着)

\(T4.\quad landmine\)(先咕着)

总结:往后的考试机会不多了,要把每一次考试当成正式考试对待。

该拿的每一分都要拿到,拿不到的想办法给我拿到(什么鬼)。

能拍的给我拍上,不要划水,不要划水,不要划水!!!

posted @ 2020-11-26 21:06  syzf2222  阅读(173)  评论(0编辑  收藏  举报