2021 10.6 模拟测试 *

T1
根据期望的线性性,答案就是每个点被删除的概率求和。但是有很多点其实是等效的,所以我们缩点成一个dag,在新图上面做就好了
#include<bits/stdc++.h>
#define in read()
using namespace std;
inline int read()
{
int data=0,w=1; char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0'&&ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
return data*w;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int N=1010,M=1000005;
const int mod=998244353;
int n,m,ans;
int val[N];char x[N];
int cnt,first[N],cnt2,first2[N];
stack<int>s;
struct edge{int u,v,nxt;}e[M],e2[M];
inline void add(int u,int v){e[++cnt]=(edge){u,v,first[u]};first[u]=cnt;}
inline void add2(int u,int v){e2[++cnt2]=(edge){u,v,first2[u]};first2[u]=cnt2;}
int dfn[N],low[N],scc[N],col,siz[N],num;
bool vis[N];
inline int ad(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int mul(int a,int b){return (1ll*a*b)%mod;}
inline int qpow(int a,int b)
{
int ret=1;
while(b)
{
if(b&1) ret=mul(ret,a);
a=mul(a,a);b>>=1;
}
return ret;
}
inline void tarjan(int u)
{
s.push(u);vis[u]=1;
dfn[u]=low[u]=++num;
for(int i=first[u];i;i=e[i].nxt)
{
int v=e[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
col++;
while(1)
{
int t=s.top();s.pop();
scc[t]=col;++siz[col];
vis[t]=0;
if(t==u) break;
}
}
}
inline void dfs(int u,int k)
{
vis[u]=1;
val[u]+=siz[k];
for(int i=first2[u];i;i=e2[i].nxt)
{
int v=e2[i].v;
if(!vis[v]) dfs(v,k);
// cout<<v<<'\n';
}
}
int main()
{
// freopen("soc.in","r",stdin);
n=in;
for(int i=1;i<=n;i++)
{
scanf("%s",x);
for(int j=0;j<n;j++) if(x[j]^48) add(i,j+1);
}
for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=cnt;i++)
{
int u=e[i].u,v=e[i].v;
if(scc[u]^scc[v]) add2(scc[u],scc[v]);
// cout<<scc[u]<<' '<<scc[v]<<'\n';
}
for(int i=1;i<=col;i++)
{
memset(vis,0,sizeof(vis));
dfs(i,i);
}
for(int i=1;i<=col;i++) ans=ad(ans,mul(siz[i],qpow(val[i],mod-2)));
write(ans);
return 0;
}
T2
设\(f[i][j]\)表示到\(i\),匹配到\(j\),最少删几个,转移是若当前删,那么可以转移到\(f[i+1][trans(j,A)]\),用\(kmp\)预处理一下\(trans\),若不删,则转移到\(f[i+1][j]\)。\(trans\)表示匹配到\(i\)位,下一位如果是\(j\),那么匹配长度就是\(trans\)
#include<bits/stdc++.h>
#define re register
#define INF 0x3f3f3f3f
using namespace std;
const int N=8080;
int trans[N][30],f[2][N],fail[N];
//trans为当前匹配到第i位了 下一位如果为 j 那么匹配的长度变为 trans[i][j]
//f[i][j]表示 当前母串到了第i为 子串匹配到了第j位的最少删除次数
char s1[N],s2[N];
int len1,len2;
void getfail(){
int k=0;
fail[0] = fail[1] = 0;
for(re int j=1;j<len2;j++){
while(k&&s2[k]!=s2[j])k=fail[k];
if(s2[k]==s2[j])k++;
fail[j+1] = k;
}
}
void init(){
for(re int i=0;i<len2;i++){
for(re int k=0;k<=25;k++){
if((int)(s2[i]-'a')==k)trans[i][k]=i+1;
else trans[i][k] = trans[fail[i]][k];
}
}
}
void minx(re int &a,re int b){
((a>b)&&(a=b));
}
int main(){
scanf("%s%s",s1,s2);
len1 = strlen(s1),len2=strlen(s2);
getfail();
init();
memset(f,0x3f,sizeof(f));
if(s1[0]==s2[0])f[0][1]=0,f[0][0]=1;
else f[0][0]=0;
re int now=0;
for(re int i=0;i<len1-1;i++,now^=1){
memset(f[now^1],0x3f,sizeof(f[now^1]));
for(re int j=0;j<len2;j++){
if(f[now][j]==INF)continue;
minx(f[now^1][j] , f[now][j]+1);
minx(f[now^1][trans[j][(int)(s1[i+1]-'a')]] , f[now][j]);
}
}
re int ans=INF;
re int tmp = (len1-1)&1;
for(re int i=0;i<len2;i++)minx(ans , f[tmp][i]);
cout<<ans;
return 0;
}
这道题乱搞都可以90,直接kmp然后输出就行,数据太水了
T3
很经典的一道题,暴力可以直接\(bfs\),但是仔细看会发现我们始终只在一张图上询问,有很多状态是无用的。
有用的状态空格在指定格子旁边,有用的后继状态则是空格移动到指定格子的周边或者与指定格子交换,于是我们可以预处理出来指定格子在\((x,y)\),空格到指定格子周边的最短距离,而空格与指定格子的交换位置的距离即为1,这个可以用\(bfs\)做。
但是我们还需要记录一下状态,可以发现对于每一个指定格子都要记录四种状态,分别是上右下左,这四个分别用\(0,1,2,3\)来记录,设状态为\(d\),则对于一个点\((x,y)\)来说状态就是\((x-1)\times m+(y-1)\times 4+d\),这样子只要通过\((d+2)mod4\)就可以到对面位置了
然后根据这个建一张新图,跑一遍\(spfa\)就可以了
#include<bits/stdc++.h>
#define in read()
using namespace std;
inline int read()
{
int data=0,w=1; char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0'&&ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
return data*w;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int N=35,M=3610,inf=0x7fffffff;
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int n,m,T;
bool a[N][N],vis[M];
int predis[N][N],dis[M];
struct edge{int v,w,nxt;}e[M*5];
int first[M],cnt;
struct node{int x,y;}cur,nxt;
queue<node>q;
queue<int>que;
inline void add(int u,int v,int w){e[++cnt]=(edge){v,w,first[u]};first[u]=cnt;}
int idx(int i,int j) {return (i-1)*m+(j-1)<<2;}
void bfs(int ex,int ey,int px,int py,int d)
{
int cx,cy,nx,ny;
memset(predis,-1,sizeof(predis));
predis[px][py]=1;predis[ex][ey]=0;
cur.x=ex,cur.y=ey;
q.push(cur);
while(!q.empty())
{
cur=q.front();q.pop();
cx=cur.x,cy=cur.y;
for(int i=0;i<4;i++)
{
nx=cur.x+dx[i],ny=cur.y+dy[i];
if(a[nx][ny]&&predis[nx][ny]==-1)
{
predis[nx][ny]=predis[cx][cy]+1;
nxt.x=nx,nxt.y=ny;
q.push(nxt);
}
}
}
if(d==4) return ;
int tmp=idx(px,py);
// cout<<"tmp "<<tmp<<' '<<px<<' '<<py<<' '<<ex<<' '<<ey<<'\n';
for(int i=0;i<4;i++)
{
int x=px+dx[i],y=py+dy[i];
if(predis[x][y]>0) add(tmp+d,tmp+i,predis[x][y]);
}
add(tmp+d,idx(ex,ey)+(d+2)%4,1);
}
void spfa(int sx,int sy)
{
int tmp;
memset(dis,-1,sizeof(dis));
for(int i=0;i<4;i++)
{
int x=sx+dx[i],y=sy+dy[i];
if(predis[x][y]!=-1)
{
tmp=idx(sx,sy)+i;
dis[tmp]=predis[x][y];
que.push(tmp);
}
}
int u;
while(!que.empty())
{
u=que.front();que.pop();
vis[u]=false;
for(int i=first[u];i;i=e[i].nxt)
{
int v=e[i].v;
if(dis[v]==-1||dis[v]>dis[u]+e[i].w)
{
dis[v]=dis[u]+e[i].w;
if(!vis[v]) vis[v]=true,que.push(v);
}
}
}
}
int main()
{
#ifdef socc
freopen("soc.in","r",stdin);
freopen("soc.out","w",stdout);
#endif
n=in,m=in,T=in;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) a[i][j]=in;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j])
{
//上右下左
if(a[i-1][j]) bfs(i-1,j,i,j,0);
if(a[i][j+1]) bfs(i,j+1,i,j,1);
if(a[i+1][j]) bfs(i+1,j,i,j,2);
if(a[i][j-1]) bfs(i,j-1,i,j,3);
}
int ex,ey,sx,sy,tx,ty,ans;
while(T--)
{
ex=in,ey=in,sx=in,sy=in,tx=in,ty=in;
if(sx==tx&&sy==ty) {puts("0");continue;}
bfs(ex,ey,sx,sy,4);
spfa(sx,sy);
ans=inf;
int tmp=idx(tx,ty);
for(int i=0;i<4;i++)
if(dis[tmp+i]!=-1) ans=min(ans,dis[tmp+i]);
if(ans==inf) ans=-1;
write(ans),puts("");
}
}

浙公网安备 33010602011771号