牛客小白月賽99 C~E
C-迷宮
思路:其實能不能到達,只要看起點和終點是否能變成連通的。射線技能只能用一次,我們在起點能到的點\((x,y)\)去\(check:x,y,x-1,y-1,y+1\)是否在終點能到達的點的座標中出現。
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e3 + 10;
int n,m;
char a[N][N];
int ds[N][N],de[N][N];
bool vis[N][N];
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
bool in(int x,int y)
{
return x >= 1 && x <= n && y >= 1 && y <= m;
}
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
cin>>n>>m;
int sx,sy,ex,ey;
for(int i = 1;i <= n; i++)
{
for(int j = 1;j <= m; j++)
{
cin>>a[i][j];
if(a[i][j]=='S')
sx = i,sy = j;
if(a[i][j]=='E')
ex = i,ey = j;
}
}
queue<array<int,3>>q;
memset(ds,127,sizeof(ds));
memset(vis,false,sizeof(vis));
ds[sx][sy] = 0;
q.push({sx,sy,0});
vis[sx][sy] = true;
while(!q.empty())
{
auto [x,y,d] = q.front();
q.pop();
for(int i = 0;i < 4; i++)
{
int dx = x + dir[i][0];
int dy = y + dir[i][1];
if(in(dx,dy) && a[dx][dy] != '#' && !vis[dx][dy]){
vis[dx][dy] = true;
q.push({dx,dy,d+1});
ds[dx][dy] = d + 1;
}
}
}
vector<array<int,2>>vs;
for(int i = 1;i <= n; i++)
for(int j = 1;j <= m; j++)if(ds[i][j] < (1<<30)){
vs.push_back({i,j});
// cout<<"i = "<<i<<" j = "<<j<<"\n";
}
memset(de,127,sizeof(de));
memset(vis,false,sizeof(vis));
de[ex][ey] = 0;
q.push({ex,ey,0});
vis[ex][ey] = true;
while(!q.empty())
{
auto [x,y,d] = q.front();
q.pop();
for(int i = 0;i < 4; i++)
{
int dx = x + dir[i][0];
int dy = y + dir[i][1];
if(in(dx,dy) && a[dx][dy] != '#' && !vis[dx][dy]){
vis[dx][dy] = true;
q.push({dx,dy,d+1});
de[dx][dy] = d + 1;
}
}
}
set<int>x,y;
for(int i = 1;i <= n; i++)
for(int j = 1;j <= m; j++)if(de[i][j] < (1<<30)){
// cout<<"i = "<<i<<" j = "<<j<<"\n";
x.insert(i);
y.insert(j);
}
bool ok = false;
for(auto [i,j] : vs){
if(x.find(i) != x.end())
ok = true;
if(i-1>=1 && x.find(i-1) != x.end())
ok = true;
if(i+1<=n && x.find(i+1) != x.end())
ok = true;
if(y.find(j) != y.end())
ok = true;
if(j-1>=1 && y.find(j-1) != y.end())
ok = true;
if(j+1<=m && y.find(j+1) != y.end())
ok = true;
}
cout<<(ok?"YES":"NO")<<"\n";
return 0;
}
D-又是一年畢業季
思路:如果眨眼時間是質數,那麼它的倍數就都不可以。如果眨眼時間是合數,那麼它分解出的最小質數就是答案。
那麼我們去預處理出質數,然後找到第一個沒出現過的質數就是答案。
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 5e6 + 10;
int n;
ll tot, p[N], pr[N];
bool vis[N];
void prime(int n)
{
for (int i = 2; i <= n; i++)
{
if (!p[i]) p[i] = i, pr[++tot] = i;
for (int j = 1; j <= tot && pr[j] * i <= n; j++) {
p[pr[j] * i] = pr[j];
if(p[i] == pr[j]) break;
}
}
}
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
prime(N);
int t; cin>>t;
while(t--)
{
cin>>n;
vector<int>v;
for(int i = 1;i <= n; i++)
{
ll x; cin>>x;
if(x > 5e6)continue;
vis[x] = true;
v.push_back(x);
}
for(int i = 1;i <= tot; i++)
{
if(!vis[pr[i]])
{
cout<<pr[i]<<"\n";
break;
}
}
for(auto x : v)
vis[x] = false;
}
return 0;
}
E-多米諾骨牌
思路:毫無疑問是用第一個能壓倒它的去壓倒是最優的。我們記錄當前最高的,能壓就壓,如果在這之前最高的都不能壓倒的話,下一塊就作為第一塊再往後算。最後去前m大的就行了。
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int f[N];
struct ty
{
int h,x;
}a[N];
bool cmp(int x,int y)
{
return x > y;
}
bool cmp1(ty x,ty y)
{
return x.x < y.x;
}
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
int t; cin>>t;
while(t--)
{
int n,m; cin>>n>>m;
for(int i = 1;i <= n; i++)
cin>>a[i].h;
for(int i = 1;i <= n; i++)
cin>>a[i].x;
sort(a+1,a+1+n,cmp1);
int t = 1,mx = a[1].h+a[1].x;
vector<int>ans;
for(int i = 2;i <= n; i++)
{
if(mx >= a[i].x){
t++;
mx = max(mx,a[i].h+a[i].x);
}else{
ans.push_back(t);
t = 1;
mx = a[i].h + a[i].x;
}
}
ans.push_back(t);
sort(ans.begin(),ans.end(),cmp);
ll res = 0;
for(int i = 0;i < min(m,(int)ans.size());i++)
res += ans[i];
cout<<res<<"\n";
}
return 0;
}