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();
	}
}

推广一波小飞龙博客:戳这里@不会飞的小飞龙

posted @ 2022-01-29 10:06  不会飞的小飞龙  阅读(147)  评论(0编辑  收藏  举报
Live2D