原题链接:第 11 场 小白入门赛 - 蓝桥云课
目录
A. 国际博物馆日
签到题
print("museum")
B. 最小值取余
贪心。
每个数字都会被选一次,根据题目给的式子,先选的数字会被乘更多次10。为了让最后的答案尽可能小,所以我们要先选小的数字。也就是先对数组元素进行排序。
又因为每次乘10可能会让这个数很大,所以我们每次乘10的操作完后,就取模,最后输出时再取模。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int MOD = 998244353;
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n; cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a.begin() + 1, a.end());
int x = 0;
for (int i = 1; i <= n; i++) {
x = x * 10 + a[i];
x = x % MOD;
}
cout << x % MOD << endl;
return 0;
}
C. 小蓝方程
观察 a=n*a 这个式子,我们可以发现当a=0或者n=1时,式子永远成立。
- 当 a=0 时,n可以取任意值,但题目给了条件0<=n<=y(不等式包含的范围有y+1个整数),所以此时答案个数为y+1
- 当 n=1 时 ,a可以取任意值,但题目给了条件0<=a<=x(不等式包含的范围有x+1个整数),所以此时答案个数为x+1
看到这里,照理答案应该为(y+1)+ (x+1),但是我们还需要考虑一种情况,就是a=0且n=1,在以上两种情况都会被计算进答案,所以要再减去1,也就是答案为(y+1)+(x+1)-1=x+y+1
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int x, y; cin >> x >> y;
cout << x + y + 1 << endl;
return 0;
}
D. 玩偶购买
贪心。
(题目中的变量很多,需要注意对应,n—总钱数,x—单个玩具体积,y—玩具单价,a—小蓝衣柜总体积,b—小桥衣柜总体积)
我们优先给小桥买尽可能多的玩具(因为小蓝的玩具数会比小桥的少,如果想她们的总玩具数尽可能多,那我们要让小桥有尽可能多的玩具)。
根据题目要求,买玩具花的总钱数需要小于等于n,同时小蓝的玩具总体积不能超过自己的衣柜,小桥的玩具的总体积也不能超过自己的衣柜。 所以我们可以知道小桥能买的玩具的数量,为v=min(b/x,n/y)。 注意,如果此时v=0,就输出-1,并返回。(因为小桥必须必小蓝玩具多,小桥如果为0,那么小蓝只能为-1,肯定不合理)
买完小桥的玩具后,剩的钱为m=n-v*y,我们设小蓝买的玩具数为w,又因为小桥的玩具数得比小蓝多(也就是满足v>=w+1),所以,小蓝的玩具数为w=min(a/x,m/y,v-1)。
最后总数即为 v+w
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
void solve(){
int n,x,y,a,b;
cin>>n>>x>>y>>a>>b;
int v=min(b/x,n/y);
if(v==0){
cout<<-1<<endl; return;
}
int m=n-v*y;
int w=min({a/x,m/y,v-1});
cout<<v+w<<endl;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; cin>>T;
while(T--){
solve();
}
return 0;
}
E. 数学魔术家
贪心。
从贪心的角度思考,把大的数字往左放这个数会更大,把小的数字往右放这个数会更小。
数据范围很大,考虑用字符串读入。用sort(s.begin(),s.end())就可以将字符串的每个字符按字典序从小到大排序,因为题目给的是个数字串。也就实现了数位从小到大排序,也就能得到最小值。再用reverse(s.begin(),s.end())函数对sort()后的字符串翻转下就能得到最大值。
因为不能有前导0,所以处理最小值时,如果有前导0,我们就将sort()后的字符串(此时这个数字的数位已经从小到大排序了),从左往右找第一个不是0的数位,并让这个数位和第一个前导0(即s[0])交换即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
string s; cin>>s;
sort(s.begin(),s.end());
auto t=s;
reverse(t.begin(),t.end());
int k=0;
int n=(int)s.size();
while(k<n&&s[k]=='0'){
k++;
}
if(k<n) swap(s[0],s[k]);
cout<<t<<" "<<s<<endl;
return 0;
}
F. 矿石样本分析
枚举+双指针
选第i个元素,可以从左边选,也可以从右边选。
需要的最短时间为 min(i+1,n-i)。 左指针 i 初始化为0,右指针 p 初始化为n-1。因为机器人同时移动,所以这两个指针也是同时移动的。
找两个数时,一定有一个数花费时间少,另一个数花费时间多,或者两个数花费时间相同。 所以枚举花费时间更多的数a[i],当枚举到数组的i位置时,左指针 i 所在区间为[0,i],右指针 p 所在区间为[n-1-i,n-1] ,判断此时k-a[i]是否存在这两个区间其中一个即可。
而判断一个数是否存在,我们可以用set或者map(这里的set或者map只是起了一个“存储作用”,方便之后调用s.find()或者map.find()判断容器中是否存在某个数)。我们枚举时只需要枚举一半就行,同时将当前 i 指的数和 p指的数 存入set或map中。再进行判断, 如果k-a[i]存在,并且a[i]和k-a[i]不相等,就找到了答案。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N=2e5+10;
int a[N];
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n,k; cin>>n>>k;
for(int i=0;i<n;i++) cin>>a[i];
set<int> s;
int p=n-1,ans=-1;
for(int i=0;i<=n/2;i++){
s.insert(a[i]);
s.insert(a[p]);
if(s.find(k-a[i])!=s.end()&&a[i]!=k-a[i]){
ans=i+1;
break;
}
if(s.find(k-a[p])!=s.end()&&a[p]!=k-a[p]){
ans=n-p;
break;
}
p--;
}
cout<<ans<<endl;
return 0;
}