1. 程式人生 > 其它 >2022牛客寒假演算法基礎集訓營3 個人題解

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