Codeforces Round 905 (Div. 3)
A. Morning
模拟,rating 800
题干
设一个now=1
next=s[0]
先不算点击的代价,只算移动的代价:
不断用next-now,取绝对值累加起来即可。
注意把0换成10
然后再加4下点击的代价。
#include<bits/stdc++.h>
using namespace std;
#define int long long
void slove(){
string s;
cin>>s;
int cnt=0;
vector<int> a;
int len=s.size();
a.push_back(1);
for(int i=0;i<len;i++){
int t=(int)(s[i]-'0');
if(s[i]=='0')a.push_back(10);
else a.push_back(t);
}
for(int i=1;i<5;i++){
cnt+=abs(a[i]-a[i-1]);
}
cnt+=4;
cout<<cnt<<endl;
}
signed main(){
int t;
cin>>t;
while(t--){
slove();
}
}
B. Chemistry
字符串处理 rating 800
回文字符串特征:
里面的字符出现奇数次的至多只有一种。
所以我们先统计出现奇数次的字符有多少次,设为cnt。
因为我们能删掉k个字符。
所以若k>cnt,那么多出来的用偶数次的抵消即可。
若k==cnt,剩下的全是偶数次
若k<cnt,若cnt-k>1,则无法构成回文
#include<bits/stdc++.h>
using namespace std;
#define int long long
void slove(){
int n,k;
cin>>n>>k;
string s;
cin>>s;
map<char,int > m;
for(int i=0;i<s.size();i++){
m[s[i]]++;
}
int ji=0;
for(auto i:m){
if(i.second &1)ji++;
}
if(k>ji){
cout<<"YES"<<endl;
}
else if(k==ji){
cout<<"YES"<<endl;
}
else{
ji-=k;
if(ji>1){
cout<<"NO"<<endl;
}
else {
cout<<"YES"<<endl;
}
}
}
signed main(){
int t;
cin>>t;
while(t--){
slove();
}
}
C. Raspberries
数学,分类讨论 rating 1000
数字之积能被k整除的特征:
- 有一个数字是k或k的倍数
- 这些数字里有k的所有质因数
由于 2 ≤ k ≤ 5 2\leq k\leq5 2≤k≤5,只有4不是质数。
所以分为k==4 和k!=4讨论即可。
对于k!=4,只需要取模k找余数离k最近的即可。
对于k==4, 因为任何数不是偶数就是奇数,所以计算奇数偶数个数即可。
当偶数超过2个,或者存在4,答案为0.
当偶数只有一个,且奇数大于1个,则答案为1
当没有有数,如果有3,那么答案为1
如果没有3,那么答案为2
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
void slove(){
int n,k;
cin>>n>>k;
vector<int> a(n);
for(int i=0;i<n;i++)cin>>a[i];
int cnt=10;
for(int i=0;i<n;i++){
if(a[i]%k==0){
cout<<0<<endl;
return;
}
cnt=min(cnt, k-a[i]%k);
}
if(k==4){
int ji=0;
int ou=0;
for(int i=0;i<n;i++){
if(a[i]%2==0){
ou++;
}
else{
ji++;
}
}
if(ou>=2){
cout<<0<<endl;
return;
}
else if(ou>=1){
int t=min(1ll,cnt);
cout<<t<<endl;
return;
}
else {
cout<<min(2ll,cnt)<<endl;
return;
}
}
cout<<cnt<<endl;
}
signed main(){
int t;
cin>>t;
while(t--){
slove();
}
}
D. In Love
贪心 rating 1500
题目比较仁慈,只要我们的集合里面有不相交的线段,就输出yes。
所以只有全都是相交的线段时,才输出NO。
我们想想不相交条件:
存在 l i > r j ( i ! = j ) l_i>r_j(i!=j) li>rj(i!=j)
很容易想到高中数学的任意存在问题:
那么就是: l m a x > r m i n l_{max}>r_{min} lmax>rmin即可
然后随意选择一个数据结构,支持增删改查的。
multiset
最大值:*rbegin()
最小值:*begin()
查:find()
删:erase()
增:insert()
由于存在集合为空的情况。
所以使用这些函数的条件是集合不为空
所以我们特判一下集合为空的情况输出NO即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
void slove() {
int q;
cin >> q;
multiset<int> ql, qr;
while (q--) {
char ch;
cin >> ch;
int l, r;
cin >> l >> r;
if (ch == '+') {
ql.insert(l);
qr.insert(r);
if (!ql.empty() && !qr.empty()) {
int maxl = *ql.rbegin();
int minr = *qr.begin();
if (maxl > minr)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
} else {
if (ql.find(l) != ql.end())
ql.erase(ql.find(l));
if (qr.find(r) != qr.end())
qr.erase(qr.find(r));
if (!ql.empty() && !qr.empty()) {
int maxl = *ql.rbegin();
int minr = *qr.begin();
if (maxl > minr)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
else{
cout<<"NO"<<endl;
}
}
}
}
signed main() {
slove();
return 0;
}
E. Look Back
构造,数学
思路很简单,对于a[i],如果a[i]<a[i-1],那么不断乘2直到大于a[i-1]即可
但是数很大会tle 和爆longlong
所以我们再创建一个数组s[i]
含义是:应该比a[i-1]乘上多少个2
若a[i]<a[i-1]
先算原始该乘的2,再加上s[i-1]
若a[i]>a[i-1]
先计算原始可以少乘的2,若大于s[i-1]那么令为0
否则加上s[i-1]
#include<bits/stdc++.h>
using namespace std;
#define ios ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
#define int long long
#define ll long long
const int N=1e5;
int a[N];
void slove() {
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
vector<int> add(n);
for(int i=1;i<n;i++){
if(a[i]<a[i-1]){
//原始的a[i]<a[i-1],意义是,a[i]应该乘以多少个2才能不小于a[i-1]
//算出原始的add[i]---应该乘多少个2
//向上取整后的商:
int int_shang=(a[i-1]+a[i]-1)/a[i]; //先算出应该乘的数向上取整
//由于只能乘2的次方,所以找出至少乘2的多少次方
//如果二进制的最高位不等于最低位,那么多乘一次
//二进制的最高位
int max_pos=log2(int_shang);
//二进制的最低位
int min_pos= (int_shang)&(-int_shang);
min_pos=log2(min_pos);
//此时算出来的是原始的a[i]到原始的a[i-1]应该乘的2的次方
if(max_pos==min_pos){
add[i]=max_pos;
// cout<<add[i]<<endl;
}
else{
add[i]=max_pos+1;
}
//若a[i-1]到a[i-2]也需要乘,那么我们就直接累加
add[i]+=add[i-1];
}
else if(a[i]==a[i-1]){
add[i]+=add[i-1];
}
else{ //a[i]>a[i-1],计算需要少乘多少次2
if(add[i-1]==0)continue;
int int_shang=a[i]/a[i-1];
int min_pos= log2(int_shang);
if(min_pos>add[i-1])continue;
add[i]=-min_pos;
add[i]+=add[i-1];
}
}
int cnt=0;
for(int i=0;i<n;i++){
cnt+=add[i];
}
cout<<cnt<<'\n';
}
signed main() {
ios;
int T;
cin>>T;
while(T--){
slove();
}
return 0;
}
int int_shang=a[i]/a[i-1];
int min_pos= log2(int_shang);
if(min_pos>add[i-1])continue;
add[i]=-min_pos;
add[i]+=add[i-1];
}
}
int cnt=0;
for(int i=0;i<n;i++){
cnt+=add[i];
}
cout<<cnt<<‘\n’;
}
signed main() {
ios;
int T;
cin>>T;
while(T–){
slove();
}
return 0;
}