【补题计划】NOI Online 2021
【NOI Online 2021】补题记录
入门组
T1 【NOI Online 2021】切蛋糕
分类讨论啦!这个SB交了3遍才A
AC code
点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int w=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9') { if(ch=='-'){ f=-1; } ch=getchar(); }
while(ch>='0' && ch<='9') { w=(w<<3)+(w<<1)+(ch^48); ch=getchar(); }
return w*f;
}
int t,a[4];
int main()
{
t=read();
while(t--)
{
for(int i=1;i<=3;i++) a[i]=read();
sort(a+1,a+3+1);
if(!a[1] && !a[2]) { cout<<0<<endl; continue; };
if(!a[1] && (a[2]==a[3])) { cout<<1<<endl; continue; };
if(!a[1] && (a[2]!=a[3])) { cout<<2<<endl; continue; };
if(a[1]+a[2]==a[3]) { cout<<2<<endl; continue; };
if((a[1]==a[2]) || (a[2]==a[3])) { cout<<2<<endl; continue; };
cout<<3<<endl;
}
return 0;
}
T2 【NOI Online 2021】吃豆人
找规律+模拟のshabi题
AC code
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int n,ans;
int val[maxn];
int a[maxn][maxn];
int same(int x,int y)
{
if((y-x)&1) return 0;
if(x==1 && y==n) return a[(y+1)/2][(y+1)/2];
if(x==1) return a[(y+1)/2][(y+1)/2]+a[(2*n-y+1)/2][(2*n-y+1)/2];
if(y==n) return a[(n-x)/2+1][(n+x)/2]+a[(n+x)/2][(n-x)/2+1];
return a[(x+y)/2][(y-x)/2+1]+a[(y-x)/2+1][(x+y)/2]+a[n-(y-x)/2][n-(x+y)/2+1]+a[n-(x+y)/2+1][n-(y-x)/2];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int x,y;
if(i+j<=n) x=i+j-1;
else x=n+n-i-j+1;
if(j>=i) y=j-i+1;
else y=i-j+1;
val[x]+=a[i][j];
if(x!=y) val[y]+=a[i][j];
}
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
ans=max(ans,val[i]+val[j]-same(i,j));
printf("%d",ans);
return 0;
}
T3 【NOI Online 2021】重力球
这题也切力!!!感觉思路很巧妙耶!
对于每一个地图,只有障碍点四周和边界四周是可以到达的
将其称为有效的点
我们可以将其以及其它点向四周行进应到达的对应的点预处理出来
不妨对其建反边(我们从重点——两个相遇的状态倒着往前推,所以要建反边)
然后用BFS跑一个类似于最短路的东西就好
代码稍稍有点长,可以适当压行
AC code
点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<climits>
#include<algorithm>
using namespace std;
const int maxn=255;
const int maxm=2010;
inline int read()
{
int w=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')
{
w=(w<<3)+(w<<1)+(ch^48);
ch=getchar();
}
return w*f;
}
int n,m,q,tot,cnt;
int head[maxm][4];
int a[maxn][maxn];
int dis[maxm][maxm];
int x_1,x_2,y_1,y_2;
int id[maxn][maxn];
int to[maxm][maxm][4];
inline bool check(int i,int j)
{
return (a[i-1][j] || a[i+1][j] || a[i][j+1] || a[i][j-1]);
}
struct edge
{
int to,next;
}e[maxm*maxm+5];
inline void add(int x,int y,int k)
{
tot++;
e[tot].to=y;
e[tot].next=head[x][k];
head[x][k]=tot;
}
inline void BFS()
{
queue <pair<int,int> > q;
for(int i=1;i<=cnt;i++)
for(int j=1;j<=cnt;j++)
dis[i][j]=INT_MAX;
for(int i=1;i<=cnt;i++)
{
q.push(make_pair(i,i)); dis[i][i]=1;
}
while(!q.empty())
{
pair<int,int> x=q.front(); q.pop();
for(int k=0;k<=3;k++)
{
for(int i=head[x.first][k];i;i=e[i].next)
{
for(int j=head[x.second][k];j;j=e[j].next)
{
int to_1=e[i].to,to_2=e[j].to;
if(dis[to_1][to_2]==INT_MAX)
{
dis[to_1][to_2]=dis[x.first][x.second]+1;
q.push(make_pair(to_1,to_2));
}
}
}
}
}
}
inline int get_ans(int X1,int Y1,int X2,int Y2)
{
return min(dis[to[X1][Y1][0]][to[X2][Y2][0]],min(dis[to[X1][Y1][1]][to[X2][Y2][1]],min(dis[to[X1][Y1][2]][to[X2][Y2][2]],dis[to[X1][Y1][3]][to[X2][Y2][3]])));
}
int main()
{
n=read();m=read();q=read();
for(int i=1;i<=m;i++)
{
int x=read();int y=read();
a[x][y]=1;
}
for(int i=1;i<=n;i++) a[0][i]=a[n+1][i]=a[i][0]=a[i][n+1]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!a[i][j] && check(i,j)) id[i][j]=++cnt;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i][j-1]) { to[i][j][0]=id[i][j]; }
else { to[i][j][0]=to[i][j-1][0]; }
if(a[i-1][j]) { to[i][j][1]=id[i][j]; }
else { to[i][j][1]=to[i-1][j][1]; }
}
}
for(int i=n;i>=1;i--)
{
for(int j=n;j>=1;j--)
{
if(a[i][j+1]) { to[i][j][2]=id[i][j]; }
else { to[i][j][2]=to[i][j+1][2]; }
if(a[i+1][j]) { to[i][j][3]=id[i][j]; }
else { to[i][j][3]=to[i+1][j][3]; }
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(id[i][j])
{
for(int k=0;k<=3;k++) add(to[i][j][k],id[i][j],k);
}
}
}
BFS();
while(q--)
{
x_1=read();y_1=read();
x_2=read();y_2=read();
if(x_1==x_2 && y_1==y_2)
{
cout<<0<<endl;
}
else
{
int ans=get_ans(x_1,y_1,x_2,y_2);
if(ans>=INT_MAX) cout<<-1<<endl;
else cout<<ans<<endl;
}
}
return 0;
}
提高组
T1 【NOI Online 2021】愤怒的小N
不可做题。。。
T2 【NOI Online 2021】积木小赛
这东西有点水啊。。。
A选的是子序列 B是子串
所以枚举B的子串,让A与B的子串匹配
把能配上的Hash值存到res数组里
然后对res去重就好啦
PS:模数取得有点大了,记得吸氧
AC code
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=3010;
const int base=51971;
const long long mod=2005091020050911;
int n,cnt;
char A[maxn];
char B[maxn];
long long res[maxn*maxn];
int main()
{
scanf("%d%s%s",&n,A+1,B+1);
for(int i=1;i<=n;i++)
{
long long mid=0; int p=1;
for(int j=i;j<=n;j++)
{
while(p<=n && A[p]!=B[j]) p++;
if(p>n) break;
p++,cnt++;
mid=(1ll*mid*base+B[j]-'a'+1)%mod;
res[cnt]=mid;
}
}
sort(res+1,res+cnt+1);
cout<<unique(res+1,res+cnt+1)-res-1;
return 0;
}
T3 【NOI Online 2021】岛屿探险
别想了,不会。。。