1. 程式人生 > >【比賽報告】2018.10.30牛客網線上賽[牛客網NOIP賽前集訓營-提高組(第三場)] NOIP練習賽卷二十六

【比賽報告】2018.10.30牛客網線上賽[牛客網NOIP賽前集訓營-提高組(第三場)] NOIP練習賽卷二十六

題目連結

A.管道維修 數學期望

題目連結
在這裡插入圖片描述
在這裡插入圖片描述


在這裡插入圖片描述

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
#define re register
const int mod=1e9+7;
const int N=210;
template<typename tp>inline void read(tp&x)
{
	x=0;re int f=0;re char ch=getchar();
	while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	if(f)x=-x;
}
template<typename tp>inline void write(tp x)
{
	re int buf[40],p=0;
	if(x<0)putchar('-'),x=-x;
	do{
		buf[p++]=x%10;x/=10;
	}while(x);
	for(re int i=p-1;i+1;i--)putchar(buf[i]+48);
	putchar(' ');
}
template<typename tp>inline ll mul(tp x,tp y){return 1ll*x*y%mod;}
int n,m;
ll a,b,g[N][N];
ll qpow(ll a,ll b)
{
	ll ret=1;a%=mod;
	for(;b;b>>=1)
	{
		if(b&1)ret=mul(ret,a);
		a=mul(a,a);
	}
	return ret;
}
int main()
{
	//freopen("in.txt","r",stdin);
	read(n);read(m);
	for(re int i=1;i<=n;i++)
	    for(re int j=1;j<=m;j++)
	    {
	    	read(a);read(b);g[i][j]=mul(a,qpow(b,mod-2));//堵塞概率 
		}
	for(re int i=1;i<=n;i++)
	{
		for(re int j=1;j<=m;j++)
		{
			re ll t=min(min(i,j),min(n-i+1,m-j+1));
			re ll ans=0,p=g[i][j],q=g[i][j];
			for(re int k=1;k<t;k++)//一個格子需要清理的次數的期望等於需要清理至少1次的概率加
//需要清理至少2次的概率加需要清理至少3次的概率加…
			{
				for(re int l=i-k;l<=i+k;l++)
				    if(abs(i-l)==k)p=mul(p,g[l][j]);
				    else p=mul(mul(p,g[l][j-k+abs(i-l)]),g[l][j+k-abs(i-l)]);//乘上曼哈頓距離等於k被堵的概率 
				ans=(ans+k*(q-p+mod))%mod;
				q=p;
			}
			ans=(ans+t*p)%mod;write(ans);
		}
		puts("");
	}
	return 0;
}

總結

求期望的好題


B.公平競賽 bfs

題目連結
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述


在這裡插入圖片描述

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
inline int read()
{
	int s=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9')f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	if(f)s=-s;return s;
}
const int N=5e3+10;
const int M=1e6+10;
const int INF=0x3f3f3f3f;
int op,n,m,tot,hd[N<<1],vis[N<<1],len[N<<1],ans[N<<1],minn=INF,pre[N<<1];
struct Edge{
	int v,nx;
}e[M<<1];
inline void add(int u,int v)
{
	e[++tot].v=v;
	e[tot].nx=hd[u];
	hd[u]=tot;
}
inline void bfs(int s)
{
	memset(vis,0,sizeof(vis));memset(len,0,sizeof(len));memset(pre,0,sizeof(pre));
    queue<int>q;while(q.size())q.pop();q.push(s);vis[s]=1;
    while(q.size())
    {
    	int u=q.front();q.pop();
    	if(2*len[u]+1>=minn)return;
    	for(int i=hd[u];i;i=e[i].nx)
    	{
    		int v=e[i].v;
    		if(v==pre[u])continue;
    		if(!vis[v])
    		{
    			vis[v]=1;q.push(v);pre[v]=u;len[v]=len[u]+1;
			}
			else
			{
				if(len[u]+len[v]+1<minn)
				{
					minn=len[u]+len[v]+1;
					int tp=0;
					for(int j=u;j;j=pre[j])ans[++tp]=j;
					reverse(ans+1,ans+tp+1);
					for(int j=v;j;j=pre[j])ans[++tp]=j;
				}
				return;
			}
		}
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
    op=read();
    while(1)
    {
    	n=read();if(!n)break;m=read();
    	memset(hd,0,sizeof(hd));tot=0;minn=INF;
    	for(int i=1,a,b;i<=m;i++)
    	    a=read(),b=read(),add(a,b+n),add(b+n,a);
    	for(int i=1;i<=n;i++)bfs(i);
    	if(minn==INF)puts("-1");
    	else
    	{
    		printf("%d\n",minn);
    		for(int i=1;i<=minn;i++)
    		    printf("%d ",ans[i]>n?ans[i]-n:ans[i]);
    		puts("");
		}
	}
	return 0;
} 

總結

拆點後在二分圖中bfs找最小環


C.急開鎖 博弈論+打表

題目連結
在這裡插入圖片描述
在這裡插入圖片描述


在這裡插入圖片描述
在這裡插入圖片描述

#include<cstdio>
typedef long long ll;
int t,k,l,r;
ll len,f[4000010];
int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%d",&t);f[0]=1;f[1]=2;
	while(t--)
	{
		scanf("%d%lld",&k,&len);
		l=0;r=1;
		while(f[r]<len)
		{
			r++;
			while(f[l]*k<f[r])l++;
			f[r+1]=f[r]+f[l];
		}
		if(f[r]==len)puts("DOG");else puts("GOD");
	}
	return 0;
}

總結