2022牛客寒假算法基础集训营3 个人题解
2022牛客寒假算法基础集训营3 个人题解
比赛链接:2022牛客寒假算法基础集训营3
A题 智乃的Hello XXXX
题目大意:
输出“hello XXX”
思路解析:
输出“hello XXX”
AC代码:
print("hello world")
B题 智乃买瓜
题目大意:
有 \(n\) 个西瓜,重量分别为 \(w[i]\) ,可以买一个或者买半个或者不卖,问购买总重量为 \(1,2,3....m\) 时的方案数
思路解析:
\(01\) 背包,\(dp[i][j]\) 表示前 \(i\) 种西瓜重量为 \(j\) 时的方案数
转移方程: \(dp[i][j]=dp[i-1][j-w_i]+dp[i-1][j-w_i/2]+dp[i-1][j]\)
AC代码:
#include<bits/stdc++.h>
#include <cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n'
#define pii pair<int,int>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int mod=1e9+7;
const int maxn=1005;
int n,m;
int dp[maxn][maxn];
int a[maxn];
int main(){
IOS
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=0;i<=n;i++){
dp[i][0]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j]=dp[i-1][j];
if(j>=a[i])dp[i][j]=(dp[i][j]+dp[i-1][j-a[i]])%mod;
if(j>=a[i]/2)dp[i][j]=(dp[i][j]+dp[i-1][j-a[i]/2])%mod;
}
}
for(int i=1;i<=m;i++)cout<<dp[n][i]<<" ";
}
C题 智乃买瓜(another version)
题目大意:
思路解析:
AC代码:
D题 智乃的01串打乱
题目大意:
给出一个 \(01\) 串,输出去一个和原串不相同但 \(0\) 和 \(1\) 数量相同的 \(01\) 串
思路解析:
找到第一个"01"然后交换变为"10"即可
AC代码:
#include<bits/stdc++.h>
#include <cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n'
#define pii pair<int,int>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn=1e6+5;
char s[maxn];
int main(){
IOS
int n;
cin>>n;
cin>>s;
for(int i=0;i<n-1;i++){
if(s[i]!=s[i+1]){
swap(s[i],s[i+1]);
break;
}
}
for(int i=0;i<n;i++){
cout<<s[i];
}
}
E题 智乃的数字积木(easy version)
题目大意:
有一个 \(n\) 位的大整数,每一位都有一个颜色,你可以把相邻的相同颜色的位交换位置,每一次给出询问 \(P,Q\) ,输出把颜色 \(P\) 的位换为颜色 \(Q\) 之后这个大整数的最大值
思路解析:
模拟,对相邻同色区间 \(sort()\) 从大到小
AC代码:
#include<bits/stdc++.h>
#include <cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n'
#define pii pair<int,int>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn=1e6+5;
const int mod=1e9+7;
int n,m,k;
int col[maxn];
char s[maxn];
bool cmp(char x,char y){
return x>y;
}
ll dfs(){
int l=1,r=1;
for(int i=2;i<=n;i++){
if(col[i]==col[i-1])r++;
else {
sort(s+l,s+r+1,cmp);
l=i;
r++;
}
}
sort(s+l,s+r+1,cmp);
ll ans=s[1]-'0';
for(int i=2;i<=n;i++){
ans=(ans*10+s[i]-'0')%mod;
}
return ans%mod;
}
int main(){
IOS
cin>>n>>m>>k;
cin>>s+1;
for(int i=1;i<=n;i++)cin>>col[i];
cout<<dfs()<<endl;
while(k--){
int x,y;
cin>>x>>y;
for(int i=1;i<=n;i++)if(col[i]==x)col[i]=y;
cout<<dfs()<<endl;
}
}
F题 智乃的数字积木(hard version)
题目大意:
思路解析:
AC代码:
G题 智乃的树旋转(easy version)
题目大意:
给出一棵树旋转前和旋转后的父子关系,找到复原的操作
思路解析:
我们发现简单版本操作是小于等于 \(1\) 的,所以至多只还原一次
当旋转前后两颗数一模一样时,显然答案为 \(0\)
否则我们需要还原一次,那么我们就找到一个节点即可,这个节点 \(x\) 满足:
旋转后, \(x\) 的父亲节点在旋转前是 \(x\) 的儿子节点
AC代码:
#include<bits/stdc++.h>
#include <cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n'
#define pii pair<int,int>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn=1e6+5;
struct node{
int x,y;
}a[maxn],b[maxn];
int fa[maxn],ba[maxn];
int main(){
IOS
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
fa[a[i].x]=i;
fa[a[i].y]=i;
}
int ok=1,pos=0;
for(int i=1;i<=n;i++){
cin>>b[i].x>>b[i].y;
ba[b[i].x]=i;
ba[b[i].y]=i;
if(b[i].x!=a[i].x||b[i].y!=a[i].y)ok=0;
}
if(ok)cout<<"0"<<endl;
else {
for(int i=1;i<=n;i++){
int x=i,y=ba[i];
if(fa[y]==x){
cout<<1<<endl;
cout<<x<<endl;
return 0;
}
}
}
}
H题 智乃的树旋转(hard version)
题目大意:
思路解析:
AC代码:
I题 智乃的密码
题目大意:
给出一个字符串,找出满足条件子串的数量
- 密码是仅包含大小写英文字母、数字、特殊符号的字符串
- 密码的长度不少于L个字符,并且不多于R个字符
- 密码中应该至少包括大写英文字母、小写英文字母、数字、特殊符号这四类字符中的三种
思路解析:
对于每个位置,把他作为子串开头,我们二分找到最小的满足条件的区间,然后就能求出每个位置的符合条件的数量,累加即可
AC代码:
#include<bits/stdc++.h>
#include <cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n'
#define pii pair<int,int>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn=1e6+5;
int n,l,r;
char s[maxn];
int sum[maxn][5];
bool ck(int x,int y){
int tot=0;
for(int i=1;i<=4;i++){
if(sum[y][i]-sum[x-1][i]==0)tot++;
}
if(tot>1)return false;
return true;
}
int main(){
IOS
cin>>n>>l>>r;
cin>>s+1;
for(int i=1;i<=n;i++){
for(int j=1;j<=4;j++)sum[i][j]=sum[i-1][j];
if(s[i]>='a'&&s[i]<='z')sum[i][1]++;
else if(s[i]>='A'&&s[i]<='Z')sum[i][2]++;
else if(s[i]>='0'&&s[i]<='9')sum[i][3]++;
else sum[i][4]++;
}
ll ans=0;
for(int i=1;i<=n-l+1;i++){
int ll=i+l-1,rr=min(i+r-1,n);
int pos=-1;
while (ll<= rr){
int mid = ll + rr >> 1;
if (ck(i,mid))
rr = mid-1,pos=mid;
else
ll = mid + 1;
}
if(pos!=-1)ans+=min(i+r-1,n)-pos+1;
}
cout<<ans<<endl;
}
J题 智乃的C语言模除方程
题目大意:
思路解析:
AC代码:
K题 智乃的C语言模除方程(another version)
题目大意:
思路解析:
AC代码:
L题 智乃的数据库
题目大意:
给出数据库中 \(n*m\) 的一张表,按照 \(group by\) 分组后,新表中每条数据有多少个
思路解析:
把非组中的数据置 \(0\) ,然后暴力枚举判断即可
判断可使用比较 \(vector\) 的方式,也可以用 \(hash\)
AC代码:
#include<bits/stdc++.h>
#include <cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n'
#define pii pair<int,int>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn=1005;
int n,m;
vector<int>a[maxn];
map<string ,int>mp;
vector<int>q;
int vis[maxn];
int st[maxn];
stack<int>stk;
int main(){
//IOS
cin>>n>>m;
for(int i=1;i<=m;i++){
string op;
cin>>op;
mp[op]=i;
}
a->resize(n+1);
for(int i=0;i<=n;i++)a[i].resize(m+1);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
getchar();
string s;
getline(cin,s);
for(int i=0;i<s.size();i++){
if(s[i]=='Y'){
string now;
int pos=i+2;
while(s[pos]!=';'){
if(s[pos]==','){
q.push_back(mp[now]);
now="";
pos++;
continue;
}
now+=s[pos];
pos++;
}
q.push_back(mp[now]);
break;
}
}
for(int i=0;i<q.size();i++){
vis[q[i]]=1;
}
for(int j=1;j<=m;j++){
if(vis[j]==0)for(int i=1;i<=n;i++){
a[i][j]=0;
}
}
for(int i=1;i<=n;i++){
if(st[i])continue;
int now=1;
for(int j=i+1;j<=n;j++){
if(a[i]==a[j]){
now++;
st[j]=1;
}
}
stk.push(now);
}
cout<<stk.size()<<endl;
while(stk.size()){
cout<<stk.top()<<" ";
stk.pop();
}
}
推广一波小飞龙博客:戳这里@不会飞的小飞龙
本文来自博客园,作者:不会飞的小飞龙,转载请注明原文链接:https://www.cnblogs.com/xiaofeilong7816/p/15838955.html