转圈游戏
题目
快速幂。
#include<cstdio>
int n;
int mul(int a,int b){return 1ll*a*b%n;}
int power(int k){int a=10,r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
int main(){int m,k,x;scanf("%d%d%d%d",&n,&m,&k,&x),printf("%d",(x+mul(m,power(k)))%n);}
货车运输
题目
直接上Kruskal重构树。当然倍增也是可以的。
#include<bits/stdc++.h>
#define open(file) freopen(file".in","r",stdin),freopen(file".out","w",stdout)
#define N 200007
using namespace std;
namespace IO
{
char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
char Get() { return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++); }
void Flush() { fwrite(obuf,1,oS-obuf,stdout),oS=obuf; }
void Put(char x) { *oS++=x; if(oS==oT) Flush(); }
int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
void write(int x) {int top=0; if(!x) Put('0'); while(x) st[++top]=(x%10)+48,x/=10; while(top) Put(st[top--]); Put('\n'); }
}
using namespace IO;
void print(){Put('-'),Put('1'),Put('\n');}
struct Edge{int u,v,w;}edge[N];
int operator<(Edge a,Edge b){return a.w>b.w;}
int head[N],tot,Fa[N],ver[N],Next[N],val[N],vis[N],dep[N],fa[N],size[N],son[N],top[N];
void add(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}
int Find(int x){return x==Fa[x]? x:Fa[x]=Find(Fa[x]);}
void dfs(int u,int Fa)
{
size[u]=vis[u]=1;
for(int i=head[u],v;i;i=Next[i]) if((v=ver[i])^Fa) dep[v]=dep[u]+1,fa[v]=u,dfs(v,u),size[u]+=size[v],son[u]=size[v]>size[son[u]]? v:son[u];
}
void Dfs(int u,int Top)
{
top[u]=Top;
if(son[u]) Dfs(son[u],Top);
for(int i=head[u],v;i;i=Next[i]) if((v=ver[i])^son[u]&&v^fa[u]) Dfs(v,v);
}
int LCA(int u,int v)
{
while(top[u]^top[v]) dep[top[u]]>dep[top[v]]? u=fa[top[u]]:v=fa[top[v]];
return dep[u]>dep[v]? v:u;
}
int main()
{
int n=read(),m=read(),cnt=n,i,Q,u,v;
for(i=1;i<=m;++i) edge[i]=Edge{read(),read(),read()};
sort(edge+1,edge+m+1);
for(i=1;i<=n;++i) Fa[i]=i;
for(i=1;i<=m;++i) if((u=Find(edge[i].u))^(v=Find(edge[i].v))) val[++cnt]=edge[i].w,Fa[cnt]=Fa[u]=Fa[v]=cnt,add(u,cnt),add(cnt,u),add(v,cnt),add(cnt,v);
for(u=1;u<=cnt;++u) if(!vis[u]) dfs(v=Find(u),0),Dfs(v,v);
for(Q=read();Q;--Q) u=read(),v=read(),Find(u)^Find(v)? print():write(val[LCA(u,v)]);
return Flush(),0;
}
积木大赛
题目
略了。
花匠
题目
树状数组优化dp是一个非常不错的方式。
其实可以贪心优化至\(O(n)\)。
假如我们现在是一个“上-下”的形式,那么下一个需要接一个比当前大的。
如果下一个比现在这个大,我们就直接接上。
如果下一个比现在这个小,我们就拿它替换掉当前这个。
代码写的是每个有一个可能的区间。
#include<cstdio>
#include<cctype>
namespace IO
{
char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
void Put(char x){*oS++=x;if(oS==oT)Flush();}
int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('\n');}
}
using namespace IO;
int max(int a,int b){return a>b? a:b;}
const int N=1000001;
int l[N],r[N];
int main()
{
int n=read(),i,p,k,l1=0,l2=0;
for(i=1;i<=n;++i) p=read(),k=0,l[i]=p-k,r[i]=p+k;
for(p=-2e9,i=1;i<=n;++i) if(l[i]>p) p=l[i],l1+=!(l1%2); else if(r[i]<p) p=r[i],l1+=l1%2;
for(p=2e9,i=1;i<=n;++i) if(r[i]<p) p=r[i],l2+=!(l2%2); else if(l[i]>p) p=l[i],l2+=l2%2;
return !printf("%d",max(l1,l2));
}
华容道
题目
大力bfs。
#include <bits/stdc++.h>
using namespace std;
template<typename _Tp>inline void IN(_Tp&dig)
{
char c;dig=0;
while(c=getchar(),!isdigit(c));
while(isdigit(c))dig=dig*10+c-'0',c=getchar();
}
int n,m,q,mp[35][35],ex,ey,sx,sy,tx,ty,tmp[35][35],dis[35][35][35][35][4],htab[10][35][35];
bool vis[35][35];
struct P{int h,w;}dirc[4]={{-1,0},{1,0},{0,-1},{0,1}};
struct ST
{
int h,w,d,G,H;
bool operator < (const ST another)const{return G+H>another.G+another.H;}
};
queue<P> que;
priority_queue<ST> pq;
inline int H(int h,int w){return abs(h-tx)+abs(w-ty);}
inline void bfs(int x1,int y1,int x2,int y2)
{
memset(tmp,0,sizeof(tmp)),memset(vis,0,sizeof(vis));
que.push((P){x1,y1}),vis[x1][y1]=1;
for(int i=0;i<4;i++)dis[x1][y1][x2][y2][i]=-1;
while(!que.empty())
{
P F=que.front(),nxt;que.pop();
for(int i=0;i<4;i++)
{
if(F.h-dirc[i].h==x2&&F.w-dirc[i].w==y2)dis[x1][y1][x2][y2][i]=tmp[F.h][F.w];
nxt.h=F.h+dirc[i].h,nxt.w=F.w+dirc[i].w;
if(nxt.h<1||nxt.h>n||nxt.w<1||nxt.w>m)continue;
if(vis[nxt.h][nxt.w]||!mp[nxt.h][nxt.w]||(nxt.h==x2&&nxt.w==y2))continue;
tmp[nxt.h][nxt.w]=tmp[F.h][F.w]+1;
que.push(nxt),vis[nxt.h][nxt.w]=1;
}
}
}
int main()
{
IN(n),IN(m),IN(q);
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)IN(mp[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)if(mp[i][j])
for(int k=0;k<4;k++)if(mp[i+dirc[k].h][j+dirc[k].w])
bfs(i+dirc[k].h,j+dirc[k].w,i,j);
while(q--)
{
memset(htab,127,sizeof(htab));
while(!pq.empty())pq.pop();
IN(ex),IN(ey),IN(sx),IN(sy),IN(tx),IN(ty),bfs(ex,ey,sx,sy);
if(sx==tx&&sy==ty){printf("0\n");goto end;}
for(int i=0;i<4;i++)
if(dis[ex][ey][sx][sy][i]!=-1)
{
ST nxt=(ST){sx,sy,i,dis[ex][ey][sx][sy][i],H(sx,sy)};
pq.push(nxt),htab[nxt.d][nxt.h][nxt.w]=dis[ex][ey][sx][sy][i];
}
while(!pq.empty())
{
ST F=pq.top();pq.pop();
if(F.h==tx&&F.w==ty){printf("%d\n",F.G);goto end;}
int eh=F.h+dirc[F.d].h,ew=F.w+dirc[F.d].w;
for(int i=0;i<4;i++)
if(dis[eh][ew][F.h][F.w][i]!=-1)
{
ST nxt=(ST){F.h,F.w,i,F.G+dis[eh][ew][F.h][F.w][i],F.H};
if(htab[nxt.d][nxt.h][nxt.w]>F.G+dis[eh][ew][F.h][F.w][i])
pq.push(nxt),htab[nxt.d][nxt.h][nxt.w]=F.G+dis[eh][ew][F.h][F.w][i];
}
ST nxt=(ST){eh,ew,F.d^1,F.G+1,H(eh,ew)};
if(htab[nxt.d][nxt.h][nxt.w]>F.G+1)
pq.push(nxt),htab[nxt.d][nxt.h][nxt.w]=F.G+1;
}
printf("-1\n");
end:continue;
}
return 0;
}