Codeforces Round 905 (Div. 3)补题报告
A.Morning
你需要输入 个四位数密码,每次输入时你的光标都在第一个数 上,在一秒内你有两种操作:
按下光标输入一位密码。
将光标移到任意与当前数字相邻的数字。
计算输入给定密码需要的最少秒数。
我们先将sum置为4,然后拆分每一位,当前这位减去他前面这位,就是需要的时间,注意0要特判,将0位变成10
第一位是用他减去1
#include<bits/stdc++.h>
using namespace std;
int abs(int a){
if(a<0){
return -a;
}
else{
return a;
}
}
int main(){
int t;
cin>>t;
int sum=4;
while(t--){
sum=4;
int n;
cin>>n;
int a,b,c,d;
d=n%10;
c=n/10%10;
b=n/10/10%10;
a=n/10/10/10%10;
int e=1;
if(a==0){
a=10;
}
if(b==0){
b=10;
}
if(c==0){
c=10;
}
if(d==0){
d=10;
}
sum+=abs(a-e);
sum+=abs(b-a);
sum+=abs(c-b);
sum+=abs(d-c);
cout<<sum<<endl;
}
return 0;
}
B.Chemistry
给定一个字符串 ,它的长度为 ,请问能否在删除 个字符后,对字符串重新排列(任意排列)使得其成为回文字符串?
当其字符为偶数个时,一定可以可以成为回文串;当其字符为奇数个时,只有最中间的一个字符可以构成回文串,其余的都要被删除。所以就遍历一遍,找出奇数字符的数量,如果大于k+1,那么无解,否则有解。
#include<bits/stdc++.h>
using namespace std;
int t,n,m,num[50],ans;
char s[100005];
int main()
{
cin >> t;
while(t--)
{
cin >> n >> k >> s;
ans = 0;
for(int i=0;i<n;i++) num[s[i]-'a']++;//统计每个字符出现的个数
for(int i=0;i<26;i++)
{
if(num[i]%2==1) ans++;
num[i]=0;
}
if(ans-1<=m) cout <<"YES"<<endl;
else cout <<"NO" << endl;
}
return 0;
}
C.Raspberries
有一个长度为 的数组 和一个整数 ( ),你每次操作可以对数组内的任意一个数加 。如果要使得 (累乘:数组中所有数字的乘积)能被数组中所有数字的乘积整除,最小操作步数是多少?
只要a数组中有一个数字能被k整除,那么数组中所有数字的乘机能被k整除。
k的数字范围是2到5,4是一个需要特判的数,其他数只要a[i]可以被整除,就可以,而4需要特判,只要数组中有超过两个数可以被2整除,则整个数组的乘积也可以被4整除。
#include <bits/stdc++.h>
using namespace std;
int n,k;
int a[N];
void solve()
{
cin >> n >> k;
int cnt = 0;
for (int i = 0; i < n; ++i) cin >> a[i];
int ans = 1e9;
for (int i = 0; i < n; i ++)
{
int t = k - (a[i] + k) % k;
if((a[i] % k) == 0) t = 0;
ans = min(ans,t);
}
if(k == 4)
{
for (int i = 0; i < n ; i ++)
if(a[i] % 2==0) cnt ++;//统计偶数的个数
if(cnt >= 2) ans = 0; //偶数个数大于等于2 更新答案
else if(n!=1 && cnt==1) ans = min(ans, 1); //n不等于1,且偶数个数等于1,则只
需要将一个奇数变为偶数即可
else if(n-cnt >= 2) ans = min(ans,2) ;//有多个奇数,将两个奇数变为偶数即可
}
cout << ans << endl;
}
int main()
{
int t;cin >> t;
while(t --) solve();
return 0;
}
D.In Love
你有 次操作,每次操作分为两种:
- ,表示添加一条区间范围为 的线段。
- ,表示删除一条区间范围为 的线段。
问每次操作后是否存在两条线段,使得它们的区间范围没有交集。
因为题目是否两条线段是否有交集,所以我们只需要判断最左面的一个右端点,和最右面的一个左端点比较即可
在这里我们可以用到 里面的 自动排序的特性存储线段的左右端点进行增删操作。(排序不去重)
#include<bits/stdc++.h>
using namespace std;
multiset<int> L,R;
void solve() {
char op;
int l, r;
cin >> op >> l >> r;
if(op == '+') L.insert(l), R.insert(r);
else L.erase(L.find(l)), R.erase(R.find(r));
if(L.size() && *R.begin() < *L.rbegin())
puts("YES");
else puts("NO");
}
int main()
{
int t;
cin >> t;
while(t--) solve();
return 0;
}
后面的题老师没讲