黑龙江职业学院校赛第二场题解
Posted MangataTS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了黑龙江职业学院校赛第二场题解相关的知识,希望对你有一定的参考价值。
前言
由于本人比较菜,只做出了9题,所以下面都是个人见解,如果有问题欢迎在评论区告诉我。总体而言题目偏简单的
比赛链接:https://ac.nowcoder.com/acm/contest/27150
A.龙职院卷怪争霸(暴力枚举)
思路
因为数据范围很小只有100,所以直接暴力枚举二重循环即可,当然也可以用单调栈做,单调栈学习链接:https://blog.csdn.net/m0_46201544/article/details/118891706
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000009
#define endl "\\n"
#define PII pair<int,int>
ll ksm(ll a,ll b)
ll ans = 1;
for(;b;b>>=1LL)
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
return ans;
ll lowbit(ll x)return -x & x;
const int N = 2e6+10;
ll n,a[N],b[N];
int main()
cin>>n;
for(int i = 1;i <= n; ++i)
cin>>a[i];
for(int j = i - 1;j >= 1; --j)
if(a[i] > a[j]) b[i]++;
for(int i = 1;i <= n; ++i)
cout<<b[i]<<" \\n"[i==n];
return 0;
B.最后一个签到 还是个字符串基础题(STL)
思路
我们要求的是不同种字符串的数量,那么我们可以手写字符串hash,然后来判断有多少不同的,由于STL很方便,所以我们直接用map<string,bool>
和.size()
就可快速求出不同种字符串的数量
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000009
#define endl "\\n"
#define PII pair<int,int>
ll ksm(ll a,ll b)
ll ans = 1;
for(;b;b>>=1LL)
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
return ans;
ll lowbit(ll x)return -x & x;
const int N = 2e6+10;
int n,a[N];
map<string,bool> vis;
int main()
string ch;
cin>>n;
for(int i = 1;i <= n; ++i) cin>>ch,vis[ch] = true;
cout<<vis.size()<<endl;
return 0;
C.送你们一个字符串的经典题吧(KMP的next)
思路
看到求前后缀,如果直接暴力大概率是T的,所以我们想想能不能快速求的公共前后缀呢,我们能想到kmp
这个东西,求其next数组的时候不就把公共前后缀求出来了吗,所以直接求一下next数组即可,KMP学习链接:https://blog.csdn.net/m0_46201544/article/details/118560016
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000009
#define endl "\\n"
#define PII pair<int,int>
ll ksm(ll a,ll b)
ll ans = 1;
for(;b;b>>=1LL)
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
return ans;
ll lowbit(ll x)return -x & x;
const int N = 2e6+10;
int n,a[N];
int nextt[N];
char S[N],T[N];
int len1,len2;
void get_next() //获取next数组
int i = 0,j = -1;
nextt[0] = -1;//很重要
while(i < len1)
if(j == -1 || S[i] == S[j])
nextt[++i] = ++j;
else
j = nextt[j];
int main()
cin>>S;
len1 = strlen(S);
get_next();
for(int i = 1;i <= len1; ++i)
cout<<nextt[i]<<" \\n"[i==n];
return 0;
D.交换机(并查集)
思路
我们会发现,智乃的群聊是无用信息,我们记录清楚姐姐的群聊,然后对互通的群聊进行一个合并操作,然后再用一个vis标记一下清楚姐姐在的群聊的所有祖先节点,然后每次在智乃查询的时候看一下是否和清楚姐姐在一个关系集合中。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000009
#define endl "\\n"
#define PII pair<int,int>
ll ksm(ll a,ll b)
ll ans = 1;
for(;b;b>>=1LL)
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
return ans;
ll lowbit(ll x)return -x & x;
const int N = 2e4+10;
ll n,zn,qc,z,q;
ll a[N],b[N],c[N];
map<ll,bool> vis;
map<ll,ll>fa;
ll find(ll x)
ll t = x;
while(t != fa[t])
t = fa[t];
while(x!= fa[x])
ll temp = fa[x];
fa[x] = t;
x = temp;
return x;
int main()
scanf("%lld %lld %lld %lld %lld",&n,&zn,&qc,&z,&q);
// cin>>n>>zn>>qc>>z>>q;
for(int i = 1;i <= n; ++i) scanf("%lld",&a[i]),fa[a[i]] = a[i];//cin>>a[i],
for(int i = 1;i <= zn; ++i) scanf("%lld",&b[i]);//cin>>b[i];
for(int i = 1;i <= qc; ++i) scanf("%lld",&c[i]);//cin>>c[i];
while(z--)
ll u,v;
scanf("%lld%lld",&u,&v);
u = find(u);
v = find(v);
if(u != v) fa[v] = u;
for(int i = 1;i <= qc; ++i) vis[find(c[i])] = true;
ll k;
while(q--)
scanf("%lld",&k);
k = find(k);
if(vis[k])
puts("wa");
else
puts("ac");
return 0;
/*
5 3 2 3 3
1 2 3 4 5
1 3 5
2 4
1 2
1 4
1 5
3
*/
E.采购(完全背包)
思路
没啥好说的,一个物品可以选无数次,然后背包体积为V,所以直接完全背包跑一下即可
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 10005
int f[N];
int v[N],w[N];
int n,V;
int main()
scanf("%d%d",&n,&V);
for(int i = 1; i <= n; ++i) scanf("%d%d",&w[i], &v[i]);
for(int i = 1; i <= n; ++i)
for(int j = w[i]; j <= V; ++j)
f[j] = max(f[j], f[j-w[i]]+v[i]);
printf("%d\\n",f[V]);
return 0;
F.字符串(STL)
思路
如果不会string的find的话,那么直接暴力二重循环匹配即可,如果会的话,直接通过find函数查找即可
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000009
#define endl "\\n"
#define PII pair<int,int>
ll ksm(ll a,ll b)
ll ans = 1;
for(;b;b>>=1LL)
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
return ans;
ll lowbit(ll x)return -x & x;
const int N = 2e6+10;
int n,a[N];
int main()
string s1,s2;
cin>>s1>>s2;
if(s1.find(s2) != -1) puts("YES");
else puts("NO");
return 0;
G.求素数(欧拉筛+二分)
思路
因为要求一个素数区间的素数个数,并且这个区间达到了 1 e 8 1e8 1e8,那么我们只能考虑使用欧拉筛(线性筛)将素数放在一个数组或者容器中,然后通过二分查找的方式进行一个 l o g 2 n log_2n log2n级别的查询。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000009
#define endl "\\n"
#define PII pair<int,int>
ll ksm(ll a,ll b)
ll ans = 1;
for(;b;b>>=1LL)
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
return ans;
ll lowbit(ll x)return -x & x;
const int N = 100000005;
int prime[7000000];
bool vis[N];
int cnt = 0;
void get_prime()
memset(vis,true,sizeof vis);
memset(prime,0,sizeof prime);
vis[0] = vis[1] = false;
for(int i = 2; i <= N; ++i)
if (vis[i])
prime[cnt++] = i;
for(int j = 0;j <= cnt && i*prime[j] < N; ++j)
vis[i * prime[j]] = false;
if (i % prime[j] == 0) //避免重复筛选
break;
int find(int k)
int l = -1,r = cnt;
while(l + 1 < r)
int mid = l + r >> 1;
if(prime[mid] <= k) l = mid;
else r = mid;
return r;
int main()
get_prime();
int t;
scanf("%d",&t);
int n,m;
while(t--)
scanf("%d%d",&n,&m);
printf("%d\\n",find(m)-find(n-1));
return 0;
H.玩游戏(思维)
思路
因为起点是从1开始的,并且每次只能跳偶数次,所以我们会发现只有当终点是奇数的时候我们才能恰好跳到,否则我们是不能跳到的
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000009
#define endl "\\n"
#define PII pair<int,int>
ll ksm(ll a,ll b)
ll ans = 1;
for(;b;b>>=以上是关于黑龙江职业学院校赛第二场题解的主要内容,如果未能解决你的问题,请参考以下文章
第十二届蓝桥杯省赛第二场C++B组 真题题解(详细讲解+代码分析)看这篇就够了~~~
Contest1592 - 2018-2019赛季多校联合新生训练赛第二场(部分题解)