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