Codeforces Round #657 (Div. 2)A~C题解

发布于 2020-07-19  0 次阅读


A. Acacius and String

思路:

解题的时候觉得太暴力了,以为有更好的方法就直接放弃了,结果真的就是暴力(哭辽)
(字符串与‘abacaba’暴力匹配(?不算匹配成功)记为函数count)
1、首先直接count,如果匹配到成功的次数大于2,直接输出NO,成功次数等于1书输出YES,并且将字符串的?替换成除abc外任意字符,成功次数为0考虑处理?后进行匹配。
2、对字符串进行暴力匹配(处理?),首先将匹配字段的?改成尽可能的匹配的字符,然后再count,返回值为1的话即为匹配成功,输出YES并且将剩余的?换成除abc外任意字符。返回值不为1则字符串回溯重新继续匹配。

AC Code:

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
const double pi = acos(-1.0);
#define INF 0x3f3f3f3f
// #define TDS_ACM_LOCAL
inline void read(int &x) {
	char ch = getchar(); int f = 1; x = 0;
	while (!isdigit(ch) && ch^'-') ch = getchar();
	if (ch == '-') f = -1, ch = getchar();
	while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
	x *= f;
}
int t, n;
string s="abacaba", s2;

int count(string str){
    int flag, ans=0;
    for(int i=0; i<=str.size()-7; i++){
        flag=1;
        for(int j=0; j<7; j++)
            if(str[i+j]!=s[j]) {flag=0; break;}
        if(flag)
            ans++;
    }
    return ans;
}

void print(string str){
    cout<<"YES"<<endl;
    for(int i=0; i<str.size(); i++){
        if(str[i]=='?') str[i]='z';
        cout<<str[i];
    }
    cout<<endl;
}

void solve(){
    read(n);
    cin>>s2;
    int k=count(s2), flag, fflag=0;
    if(k>1) {cout<<"NO"<<endl; return ;}
    if(k==1)    {print(s2); return ;}
    string temp=s2;
    for(int i=0; i<=s2.size()-7; i++){
        s2=temp;
        flag=1;
        for(int j=0; j<7; j++){
            if(s2[i+j]=='?')    s2[i+j]=s[j];
            if(s2[i+j]!=s[j])   {flag=0; break;}
        }
        if(flag){
            k=count(s2);
            if(k==1)    {print(s2); fflag=1;}
        }
        if(fflag)
            break;
    }
    if(!fflag)  cout<<"NO"<<endl;
    return ;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
#ifdef TDS_ACM_LOCAL
    freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
    freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
    read(t);
    while(t--)  solve();
    return 0;
}

B. Dubious Cyrpto

思路:

首先将b-c从等式中分离开考虑,它可以使na在以自身为中心的 [ l - r , r - l ] 范围内波动。
对于m的处理,可以m=na+(波动区间),所以在区间 [ l , r ] 枚举a的取值,得m%a(基于n),a-m%a(基于n+1)将取模后的范围分为0->m%a和a-m%a->a再判断值是否在波动区间内再对b和c的取值进行考虑
注:首先应该考虑a-m%a,因为这种情况n必为正整数。

AC Code:

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
const double pi = acos(-1.0);
#define INF 0x3f3f3f3f
typedef long long LL;
// #define TDS_ACM_LOCAL

LL l, r, m, t;
LL a, b, c;
LL c1, c2;
void solve(){
    cin>>l>>r>>m;
    for(int i=l; i<=r; i++){
        c1=m%i, c2=i-m%i;
        a=i;
        if(c2<=r-l)    {b=l, c=l+c2; break;}
        if(c1<=r-l)    {b=l+c1, c=l; break;}
    }
    cout<<a<<" "<<b<<" "<<c<<endl;
    return ;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
#ifdef TDS_ACM_LOCAL
    freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
    freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
    cin>>t;
    while(t--)  solve();
    return 0;
}

C. Choosing flowers

思路:

按照a对花的价值进行非递增排序,枚举选a的每种情况,因为a可能大于b,所以二分求得当前枚举的b在a中排序后的位置,在n的范围内买下大于b的a,然后剩下的n买b,在买b前判断一下该枚举值的a是否购买,可以用前缀和维护一下二分得到b在a的位置时需要加上的sum_a
对于为什么b一直只取一种做一下说明:假如说有两种及其以上的花会取多次,那么全换成内这些花的b最高的那一种的话值会更大

AC Code:

#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5 + 9;
// #define TDS_ACM_LOCAL
pair<long long, long long>x[N];
int t, n, m;

int find(long long v){
    int l=1, r=m, ans=0;
    while(l<=r){
        int mid=(l+r)>>1;
        if(x[mid].first>v)  {ans=mid, l=mid+1;}
        else    r=mid-1;
    }
    return ans;
}

void solve(){
    int ind=0, cnt=0, hb=0;
    long long sum[N]={0};
    long long res=0, ans=0;
    cin>>n>>m;
    for(int i=1; i<=m; i++) {cin>>x[i].first>>x[i].second;}
    sort(x+1, x+1+m, greater<pair<long long,long long>>());      //从大到小排序
    for(int i=1; i<=m; i++) {sum[i]+=sum[i-1]+x[i].first;}       //求前缀和 
    for(int i=1; i<=m; i++){
        ind=find(x[i].second);                                   //二分求得b在排好序后a的位置
        cnt=min(ind, n-1);                                       //在n的有效范围内买a
        res=sum[cnt];
        hb=n-cnt;                                                //n的剩余值去买b
        if(i>cnt)   {res+=x[i].first; hb--;}                     //判断当前枚举的a是否购买
        res+=1LL *hb*x[i].second;
        ans=max(ans, res);                                       //求得枚举的最大价值
    }
    cout<<ans<<endl;
    return ;
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
#ifdef TDS_ACM_LOCAL
    freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
    freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
    cin>>t;
    while(t--)  solve();
    return 0;
}


平平无奇的在校大学生