【比賽報告】2018.10.30牛客網線上賽[牛客網NOIP賽前集訓營-提高組(第三場)] NOIP練習賽卷二十六
阿新 • • 發佈:2018-11-01
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; }
總結
無