目录
第一题,吃糖果
排序 和 贪心。贪心注意到先吃甜度之较小的糖果是最优的。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int a[200010];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
int sum=0,res=0;
for(int i=1;i<=n;i++){
if(a[i]<=k){
res++;
k-=a[i];
}else{
break;
}
}
cout<<res<<endl;
return 0;
}
第二题,游游的重组偶数
数学知识 、分类讨论。注意到末尾为偶数即偶数,移动一个偶数到末尾即可。特别的,如果这样做会导致前导零,需要特判。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int a[15];
void solve(){
string s;cin>>s;
int n = s.size();
int t = s[n-1]-'0';
if(t%2==0){
cout<<s<<endl;
return ;
}
int num=-1;
for(int i=0;i<n;i++){
int tmp=s[i]-'0';
if(tmp%2==0) {
num=i;
}
}
if(num==-1){
cout<<-1<<endl;
return;
}
for(int i=0;i<n;i++){
if(i!=num) cout<<s[i];
}
cout<<s[num]<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _=1;
cin>>_;
while(_--){
solve();
}
return 0;
}
第三题,开心还是难过
字符串 和 暴力模拟。检查给定的字符串中是否存在emoji,由于范围较小。直接暴力即可,不需要使用字符串匹配算法,但是如果会用,也可以直接使用诸如find一类的内置函数。
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
string s;
getline(cin,s);
cout<<s<<endl;
int n=s.size();
int l=0,r=0;
if(n<3){
cout<<"None"<<endl;
return ;
}
for(int i=0;i<n-2;i++){
if(s[i]==':'&& s[i+1]=='-'){
if(s[i+2]=='(')l++;
if(s[i+2]==')') r++;
}
}
if(r==0&&l==0){
cout<<"None"<<endl;
return;
}
if(r>l) cout<<"Happy"<<endl;
if(r==l) cout<<"Just so so"<<endl;
if(r<l) cout<<"Sad"<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _=1;
//cin>>_;
while(_--){
solve();
}
return 0;
}
第四题,小欧的平面连线
几何 和 数学推导,我们需要对平面上的点进行配对,使得连线与坐标轴的交点尽可能多。关键在于理解线段与坐标轴相交的条件,以及如何通过巧妙的配对来最大化权值和。考虑从点的分布入手,第一三象限,第二四象限的点连接权值为2。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
void solve(){
int n;
cin>>n;
int num1=0,num2=0,num3=0,num4=0;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
if(x>0&&y>0) num1++;
else if(x<0&&y>0) num2++;
else if(x<0&&y<0) num3++;
else if(x>0&&y<0)num4++;
}
int tmp1=min(num1,num3);
int tmp2=min(num2,num4);
int tmp=min(num1+num3-2*tmp1,num2+num4-2*tmp2);
int res = 2*tmp1 + 2*tmp2 + tmp;
cout<<res<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _=1;
//cin>>_;
while(_--){
solve();
}
return 0;
}
第五题,小红的四子棋
模拟 、搜索 。对于每一个位置检查其是否位于一个合法的连珠序列上即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
char s[110][110];
int n,m;
int fp1(char c,int i,int j){ // 横
int num=1;
for(int k=1;k<=7;k++){
if(j+k>m) break;
if(s[i][j+k]!=c) break;
num++;
}
for(int k=1;k<=7;k++){
if(j-k<1) break;
if(s[i][j-k]!=c) break;
num++;
}
return num;
}
int fp2(char c,int i,int j){ // 竖
int num=1;
for(int k=1;k<=7;k++){
if(i+k>n) break;
if(s[i+k][j]!=c) break;
num++;
}
for(int k=1;k<=7;k++){
if(i-k<1) break;
if(s[i-k][j]!=c) break;
num++;
}
return num;
}
int fp3(char c,int i,int j){ // 对角线 1
int num=1;
for(int k=1;k<=7;k++){
if(i+k>n||j+k>m) break;
if(s[i+k][j+k]!=c) break;
num++;
}
for(int k=1;k<=7;k++){
if(i-k<1||j-k<1) break;
if(s[i-k][j-k]!=c) break;
num++;
}
return num;
}
int fp4(char c,int i,int j){ // 对角线 2
int num=1;
for(int k=1;k<=7;k++){
if(i-k<1||j+k>m) break;
if(s[i-k][j+k]!=c) break;
num++;
}
for(int k=1;k<=7;k++){
if(i+k>n||j-k<1) break;
if(s[i+k][j-k]!=c) break;
num++;
}
return num;
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>s[i][j];
}
}
int maxr=0,maxp=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int num1=0,num2=0,num3=0,num4=0;
num1=fp1(s[i][j],i,j);
num2=fp2(s[i][j],i,j);
num3=fp3(s[i][j],i,j);
num4=fp4(s[i][j],i,j);
int num=max(max(num1,num2),max(num3,num4));
if(s[i][j]=='r'){
maxr=max(maxr,num);
}else if(s[i][j]=='p'){
maxp=max(maxp,num);
}
}
}
if(maxr>=4){
cout<<"kou"<<endl;
return ;
}
if(maxp>=4){
cout<<"yukari"<<endl;
return ;
}
cout<<"to be continued"<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _=1;
//cin>>_;
while(_--){
solve();
}
return 0;
}
第六题,小红的数组操作
二分搜索 、贪心策略 。要求在进行 k 次操作后,使数组的最大值尽可能小。我们需要思考如何分配这 k 次操作,使得最终的数组的最大值最小。一个有效的思路是尝试找到一个最小的最大值,使得在 k 次操作内可以将数组中的所有元素降低到不超过这个值。执行二分查找后检查答案是否符合题意要求即可。本题难度不高,但是不太容易想到二分这一思路。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
void solve(){
int n, k, x;
cin >> n >> k >> x;
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
int low = a[0] - k * x;
int high = *max_element(a.begin(), a.end());
while (low < high) {
int mid = (high + low) / 2, tmp = 0;
for (int i = 0; i < n; ++i) {
if (a[i] > mid) {
tmp += (a[i] - mid + x - 1) / x; // (a[i] - mid) / 2 的向上取整
}
}
if (tmp <= k) high = mid;
else low = mid + 1;
}
cout << low << endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int _=1;
//cin>>_;
while(_--){
solve();
}
return 0;
}